Cloned SEACAS for EXODUS library with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.4 KiB

2 years ago
/*
* Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
* NTESS, the U.S. Government retains certain rights in this software.
*
* See packages/seacas/LICENSE for details
*/
#include "defs.h"
#include "structs.h"
#include <math.h>
#include <stdio.h>
double opt2d(
/* Compute rotation angle to minimize distance to discrete points. */
struct vtx_data **graph, /* data structure with vertex weights */
double **yvecs, /* eigenvectors */
int nvtxs, /* total number of vertices */
int nmyvtxs /* number of vertices I own */
)
{
extern int DEBUG_OPTIMIZE; /* debug flag for optimization */
double *aptr, *bptr; /* loop through yvecs */
double coeffs[5]; /* various products of yvecs */
double a, b; /* temporary values */
double func = 0.0; /* value of function to be minimized */
double grad, hess; /* first and 2nd derivatives of function */
double grad_min; /* acceptably small gradient */
double theta; /* angle being optimized */
double step; /* change in angle */
double step_max; /* maximum allowed step */
double step_min; /* minimum step => convergence */
double hess_min; /* value for hessian is < 0 */
double hfact; /* scaling for min tolerated hessian */
double w; /* vertex weight squared */
double pdtol; /* allowed error in hessian pd-ness */
int pdflag; /* is hessian positive semi-definite? */
int i; /* loop counter */
/* Set parameters. */
step_max = PI / 8;
step_min = 2.0e-5;
grad_min = 1.0e-7;
pdtol = 1.0e-8;
hfact = 2;
for (i = 0; i < 5; i++) {
coeffs[i] = 0;
}
aptr = yvecs[1] + 1;
bptr = yvecs[2] + 1;
for (i = 1; i <= nmyvtxs; i++) {
a = *aptr++;
b = *bptr++;
w = graph[i]->vwgt;
if (w == 1) {
coeffs[0] += a * a * a * a;
coeffs[1] += a * a * a * b;
coeffs[2] += a * a * b * b;
coeffs[3] += a * b * b * b;
coeffs[4] += b * b * b * b;
}
else {
w = 1 / (w * w);
coeffs[0] += a * a * a * a * w;
coeffs[1] += a * a * a * b * w;
coeffs[2] += a * a * b * b * w;
coeffs[3] += a * b * b * b * w;
coeffs[4] += b * b * b * b * w;
}
}
/* Adjust for normalization of eigenvectors. */
/* This should make tolerances independent of vector length */
for (i = 0; i < 5; i++) {
coeffs[i] *= nvtxs;
}
i = 0;
theta = 0.0;
step = step_max;
pdflag = FALSE;
grad = 0;
while (fabs(step) >= step_min && (!pdflag || fabs(grad) > grad_min)) {
func = func2d(coeffs, theta);
grad = grad2d(coeffs, theta);
hess = hess2d(coeffs);
if (hess < -pdtol) {
pdflag = FALSE;
}
else {
pdflag = TRUE;
}
hess_min = hfact * fabs(grad) / step_max;
if (hess < hess_min) {
hess = hess_min;
}
if (fabs(grad) > fabs(hess * step_max)) {
step = -step_max * sign(grad);
}
else {
step = -grad / hess;
}
theta += step;
if (fabs(step) < step_min && !pdflag) { /* Convergence to non-min. */
step = step_min;
theta += step;
}
i++;
}
if (DEBUG_OPTIMIZE > 0) {
printf("After %d passes, func=%e, theta = %f\n", i, func, theta);
}
return (theta);
}