39 #ifndef Mesquite_NonSmoothSteepestDescent_hpp
40 #define Mesquite_NonSmoothSteepestDescent_hpp
43 #include "VertexMover.hpp"
44 #include "ObjectiveFunction.hpp"
45 #include "MsqFreeVertexIndexIterator.hpp"
46 #include "MsqDebug.hpp"
53 #define MSQ_BIG_POS_NMBR 1E300
54 #define MSQ_BIG_NEG_NMBR -1E300
55 #define MSQ_MAX_OPT_ITER 20
59 #define MSQ_NO_EQUIL 101
60 #define MSQ_CHECK_TOP_DOWN 102
61 #define MSQ_CHECK_BOTTOM_UP 103
62 #define MSQ_TWO_PT_PLANE 104
63 #define MSQ_THREE_PT_PLANE 105
64 #define MSQ_CHECK_Y_COORD_DIRECTION 106
65 #define MSQ_CHECK_X_COORD_DIRECTION 107
66 #define MSQ_CHECK_Z_COORD_DIRECTION 108
68 #define MSQ_HULL_TEST_ERROR 110
70 #define MSQ_STEP_ACCEPTED 100
71 #define MSQ_IMP_TOO_SMALL 101
72 #define MSQ_FLAT_NO_IMP 102
73 #define MSQ_STEP_TOO_SMALL 103
74 #define MSQ_EQUILIBRIUM 104
75 #define MSQ_ZERO_SEARCH 105
76 #define MSQ_MAX_ITER_EXCEEDED 106
78 #define MSQ_STEP_DONE 101
79 #define MSQ_STEP_NOT_DONE 102
81 #define MAX_NUM_ELEMENTS 150
82 #define MAX_FUNC_PER_ELEMENT 6
83 #define MSQ_MACHINE_EPS 1E-16
86 #define MSQ_MAX(a,b) (a > b ? a : b)
87 #define MSQ_MIN(a,b) (a < b ? a : b)
88 #define MSQ_LESS_THAN_MACHINE_EPS(x) ( ((fabs(x)+1.0) > 1.0) ? 0 : 1 )
90 #define MSQ_DOT(c,a,b,n) {\
92 if (n==2) c = a[0]*b[0] + a[1]*b[1]; \
93 else if (n==3) c = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];\
96 for (i99=0;i99<n;i99++) c += a[i99]*b[i99]; \
100 #define MSQ_NORMALIZE(v,n) {\
104 mag99 = sqrt(v[0]*v[0] + v[1]*v[1]) ; \
110 mag99 = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) ; \
118 for (i99=0;i99<n;i99++) mag99+=v[i99]+v[i99]; \
120 for (i99=0;i99<n;i99++) v[i99] = v[i99]/mag99;\
125 #define MSQ_COPY_VECTOR(a,b,n) { \
128 a[0] = b[0]; a[1] = b[1]; \
130 a[0] = b[0]; a[1] = b[1]; a[2] = b[2]; \
132 for (i99=0;i99<n;i99++) a[i99] = b[i99]; \
145 class NonSmoothSteepestDescent :
public VertexMover
228 void find_plane_points(
int dir1,
int dir2,
double **vec,
int num_vec,
double *pt1,
229 double *pt2,
double*pt3,
int *opt_status,
MsqError &err);
236 void solve2x2(
double a11,
double a12,
double a21,
double a22,
237 double b1,
double b2,
double **
x,
MsqError &err);
259 bool valid_bool=
true;
268 valid_bool = currentQM->evaluate_element(*patch_data,
269 &(patch_data->element_by_index(i)),
284 double delta = 10e-6;
293 double *func, *fdelta;
294 func = (
double *)malloc(
sizeof(
double)*150);
295 fdelta = (
double *)malloc(
sizeof(
double)*150);
306 for (
int j=0;
j<3;
j++) {
336 ActiveSet *active_set,
341 double active_value0;
345 MSQ_DBGOUT(2) <<
"\nFinding the active set\n";
351 active_set->num_active = 1;
352 active_set->num_equal = 0;
353 active_set->active_ind[0] = 0;
354 active_set->true_active_value =
function[0];
361 function_val =
function[
i];
362 active_set->true_active_value =
MSQ_MAX(function_val,active_set->true_active_value);
363 active_value0 =
function[active_set->active_ind[0]];
364 temp = fabs(function_val - active_value0);
366 if ( function_val > active_value0 ) {
368 active_set->num_active = 1;
369 active_set->num_equal = 0;
370 active_set->active_ind[0] =
i;
372 active_set->num_active += 1;
373 ind = active_set->num_active - 1;
374 active_set->active_ind[ind] =
i;
376 active_set->num_equal += 1;
381 active_set->num_active += 1;
382 ind = active_set->num_active - 1;
383 active_set->active_ind[ind] =
i;
385 active_set->num_equal += 1;
408 double dEps = 1.e-13;
410 double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4;
421 double a = x2*y3 - x3*y2;
439 double dDX2 = x2 - x1;
440 double dDX3 = x3 - x1;
441 double dDX4 = x4 - x1;
443 double dDY2 = y2 - y1;
444 double dDY3 = y3 - y1;
445 double dDY4 = y4 - y1;
447 double dDZ2 = z2 - z1;
448 double dDZ3 = z3 - z1;
449 double dDZ4 = z4 - z1;
452 double dDet = dDX2*dDY3*dDZ4 + dDX3*dDY4*dDZ2 + dDX4*dDY2*dDZ3
453 - dDZ2*dDY3*dDX4 - dDZ3*dDY4*dDX2 - dDZ4*dDY2*dDX3 ;
456 double dScale = (
sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) +
458 sqrt((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3) +
460 sqrt((x1-x4)*(x1-x4) + (y1-y4)*(y1-y4) +
462 sqrt((x2-x3)*(x2-x3) + (y2-y3)*(y2-y3) +
464 sqrt((x2-x4)*(x2-x4) + (y2-y4)*(y2-y4) +
466 sqrt((x3-x4)*(x3-x4) + (y3-y4)*(y3-y4) +
467 (z3-z4)*(z3-z4)) ) / 6.;
477 dDet /= (dScale*dScale*dScale);
484 else if (dDet < -dEps)
509 (*dir) =(
double **)malloc(
sizeof(
double *)*num_active);
510 for (i=0;i<num_active;i++) {
511 (*dir)[
i] =(
double *)malloc(
sizeof(
double)*
mDimension);
524 double test_dot, dot;
527 MSQ_DOT(test_dot,vec[0],normal,3);
530 MSQ_DOT(test_dot,vec[ind],normal,3);
534 for (i=ind;i<num_vec;i++) {
536 if ( ((dot>0 && test_dot<0) || (dot<0 && test_dot>0)) &&
553 double vecA[3], vecB[3];
556 vecA[
i] = pt2[
i] - pt1[
i];
557 vecB[
i] = pt3[
i] - pt1[
i];
559 cross[0] = vecA[1]*vecB[2] - vecA[2]*vecB[1];
560 cross[1] = vecA[2]*vecB[0] - vecA[0]*vecB[2];
561 cross[2] = vecA[0]*vecB[1] - vecA[1]*vecB[0];
570 int status, dir_done;
571 double pt1[3], pt2[3], pt3[3];
586 vec, num_vec, pt1, pt2, pt3, &status, err);
591 vec, num_vec, pt1, pt2, pt3, &status, err);
596 vec, num_vec, pt1, pt2, pt3, &status, err);
600 pt3[0]=0.; pt3[1]=0.; pt3[2]=0.;
616 }
else if (equil == 0) {
625 MSQ_PRINT(3)(
"Not an equilibrium point\n");
633 MSQ_PRINT(3)(
"Failed to determine equil or not; status = %d\n",status);
644 if (num_active > 150) {
649 for (i=0; i<num_active; i++) {
650 for (j=i; j<num_active; j++) {
665 double mid_vec[3], mid_cos, test_cos;
677 if (num_active==numFunctionValues)
680 MSQ_PRINT(3)(
"All the function values are in the active set\n");
695 for (i=0;i<num_active;i++) {
696 for (j=i+1;j<num_active;j++) {
697 if ( fabs(-1 -
mG[i][j]) < 1E-08 ) {
699 MSQ_PRINT(3)(
"The gradients are antiparallel, eq. pt\n");
701 if (
mG[i][j] < min) {
708 if ((ind1 != -1) && (ind2 != -1)) {
711 mid_vec[
j]=.5*(dir[ind1][
j]+dir[ind2][
j]);
714 MSQ_DOT(mid_cos,dir[ind1],mid_vec,mDimension);
717 for (i=0;i<num_active;i++) {
718 if ((i != ind1) && (i != ind2)) {
719 MSQ_DOT(test_cos,dir[i],mid_vec,mDimension);
720 if ((test_cos < mid_cos) && fabs(test_cos-mid_cos) >
MSQ_MACHINE_EPS) {
728 if (mDimension == 3) {
740 double a11, a12, a13;
741 double a21, a22, a23;
742 double a31, a32, a33;
750 a11 = A[0][0]; a12=A[0][1]; a13=A[0][2];
751 a21 = A[1][0]; a22=A[1][1]; a23=A[1][2];
752 a31 = A[2][0]; a32=A[2][1]; a33=A[2][2];
754 denom = -a11*a22*a33+a11*a23*a32+a21*a12*a33-a21*a13*a32-
755 a31*a12*a23+a31*a13*a22;
773 s1 =
sqrt(a11*a11 + a12*a12 + a13*a13 +
774 a21*a21 + a22*a22 + a23*a23 +
775 a31*a31 + a32*a32 + a33*a33);
777 temp = (-a22*a33+a23*a32)/denom;
779 temp =(a12*a33-a13*a32)/denom;
781 temp = (a12*a23-a13*a22)/denom;
783 temp = (a21*a33-a23*a31)/denom;
785 temp = (a11*a33-a13*a31)/denom;
787 temp = (a11*a23-a13*a21)/denom;
789 temp = (a21*a32-a22*a31)/denom;
791 temp = (-a11*a32+a12*a31)/denom;
793 temp = (-a11*a22+a12*a21)/denom;
807 if ((n>3) || (n<1)) {
815 if (A[0][0] > 0) (*singular) =
MSQ_FALSE;
839 for (i=0;i<num_active;i++) {
840 for (j=0;j<num_active;j++) {
855 while( (k<mDimension) && (i < num_active) ) {
864 if (k==1) g_ind_1 =
i;
879 double temp_search[3];
884 if ( (mDimension != 2) && (mDimension != 3)) {
889 for (i=0;i<
mDimension;i++) temp_search[i] = 0;
892 min_projection = 1E300;
893 for (i=0; i<num_active; i++) {
898 for (j=0;j<num_active;j++) {
899 if (
mG[j][i] < 0) viable = 0;
903 if ((viable) && (
mG[
i][
i] < min_projection)) {
904 min_projection =
mG[
i][
i];
910 for (j=i+1; j<num_active; j++) {
918 b = (mG[
i][
j] - mG[
i][
i])/denom;
920 if ((b < 0) || (b > 1)) viable=0;
921 for (k=0;k<num_active;k++) {
922 if ((a*mG[k][i] + b*mG[k][j]) <= 0) viable=0;
931 g_bar[
k] = a * dir[
i][
k] + b * dir[
j][
k];
933 MSQ_DOT(projection,g_bar,g_bar,mDimension);
934 if (projection < min_projection) {
949 double a21,
double a22,
950 double b1,
double b2,
951 double **
x, MsqError &)
957 (*x)=(
double *)malloc(
sizeof(
double)*2);
960 (*x)[1] = (b2 - factor*b1)/(a22 - factor*a12);
961 (*x)[0] = (b1 - a12*(*x)[1])/a11;
964 (*x)[1] = (b1 - factor*b2)/(a12 - factor*a22);
965 (*x)[0] = (b2 - a22*(*x)[1])/a21;
979 (*P)=(
double **)malloc(
sizeof(
double *)*(num_active-1));
980 for (i=0; i<num_active-1; i++)
981 (*P)[
i]=(
double *)malloc(
sizeof(
double)*(num_active-1));
983 for (i=0;i<num_active-1;i++) {
984 (*P)[
i][
i] = mG[0][0] - 2*mG[0][i+1] + mG[i+1][i+1];
985 for (j=i+1;j<num_active-1;j++) {
986 (*P)[
i][
j] = mG[0][0] - mG[0][j+1] - mG[i+1][0] + mG[i+1][j+1];
987 (*P)[
j][
i] = (*P)[
i][
j];
1002 if (est_imp>*final_est) *final_est = est_imp;
1004 if (*final_est == 0) {
1005 *final_est = -1E300;
1009 *final_est = est_imp;
1032 double steepest_function;
1033 double steepest_grad;
1035 double min_positive_value=1E300;
1046 for (i=0;i<num_values;i++)
1053 if (fabs(mGS[
mSteepest] - mGS[i])>1E-13) {
1055 alpha_i = alpha_i/(steepest_grad - mGS[
i]);
1062 MSQ_PRINT(3)(
"Setting alpha %d %g\n",
i,alpha_i);
1064 if ((alpha_i > 0) && (alpha_i < min_positive_value)) {
1065 min_positive_value = alpha_i;
1070 if ((
mAlpha == 1E300) && (min_positive_value != 1E300)) {
1071 mAlpha = min_positive_value;
1077 MSQ_PRINT(3)(
"Setting alpha to the maximum step length\n");
1089 if (active1==NULL || active2==NULL) {
1094 active2->num_active = active1->num_active;
1095 active2->num_equal = active1->num_equal;
1096 active2->true_active_value = active1->true_active_value;
1097 for (
int i=0;i<active1->num_active;i++) {
1098 active2->active_ind[
i] = active1->active_ind[
i];
1107 if (active_set==0) {
1112 if (active_set->num_active == 0)
MSQ_DBGOUT(3)<<
"No active values\n";
1114 for (
int i=0;i<active_set->num_active;i++) {
1116 i+1,func[active_set->active_ind[
i]]);
1125 MSQ_PRINT(2)(
"\nInitializing Optimization \n");
1126 if (numFunctionValues > 150) {
1138 MSQ_PRINT(3)(
" Initialized Constants \n");
1142 for (j=0;j<3;j++)
mPDG[i][j] = 0;
1145 MSQ_PRINT(3)(
" Initialized search and PDG \n");
1155 MSQ_PRINT(3)(
" Initialized function/gradient \n");
1156 if (numFunctionValues > 150) {
1157 for (i=0;i<150;i++) {
1158 for (j=0;j<150;j++) mG[i][j] = -1;
1168 MSQ_PRINT(3)(
" Initialized prevActiveValues\n");
1175 double max_diff = 0;
1178 MSQ_PRINT(2)(
"In init_max_step_length\n");
1181 if (numElements==0) {
1185 if ((mDimension!=2) && (mDimension!=3)) {
1192 for (j=i;j<numVertices+1;j++) {
1197 if (max_diff < diff) max_diff=diff;
1200 max_diff =
sqrt(max_diff);
1202 MSQ_SETERR(err)(
"Maximum distance between incident vertices = 0\n",
1214 #endif // Mesquite_NonSmoothSteepestDescent_hpp
void find_plane_points(int dir1, int dir2, double **vec, int num_vec, double *pt1, double *pt2, double *pt3, int *opt_status, MsqError &err)
msq_stdc::size_t get_vertex_index(msq_stdc::size_t vertex_in_element) const
double * originalFunction
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
void step_acceptance(PatchData &pd, MsqError &err)
NVec< 3, T > cross(const NVec< 3, T > &u, const NVec< 3, T > &v)
void form_grammian(double **vec, MsqError &err)
Used to hold the error state and return it to the application.
void check_equilibrium(int *equil, int *opt_status, MsqError &err)
void search_direction(PatchData &pd, MsqError &err)
void form_PD_grammian(MsqError &err)
virtual void terminate_mesh_iteration(PatchData &pd, MsqError &err)
double * prevActiveValues
double ** compute_gradient(PatchData *pd, MsqError &err)
double minAcceptableImprovement
MsqMeshEntity is the Mesquite object that stores information about the elements in the mesh...
virtual void initialize(PatchData &pd, MsqError &err)
void singular_test(int n, double **A, int *singular, MsqError &err)
#define MSQ_THREE_PT_PLANE
virtual ~NonSmoothSteepestDescent()
QualityMetric * get_quality_metric()
virtual msq_std::list< QualityMetric * > get_quality_metric_list()
#define MSQ_COPY_VECTOR(a, b, n)
void minmax_opt(PatchData &pd, MsqError &err)
#define MSQ_DOT(c, a, b, n)
invalid function argument passed
int validity_check(MsqError &err)
int convex_hull_test(double **vec, int num_vec, MsqError &err)
#define MSQ_CHECK_Z_COORD_DIRECTION
void get_coordinates(double &x, double &y, double &z) const
void get_active_directions(double **gradient, double ***dir, MsqError &err)
#define MSQ_CHECK_Y_COORD_DIRECTION
#define MSQ_CHKERR(err)
Mesquite's Error Checking macro.
void init_opt(MsqError &err)
#define MSQ_CHECK_X_COORD_DIRECTION
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
void search_edges_faces(double **dir, MsqError &err)
ObjectiveFunction * objFunc
MsqMeshEntity * mConnectivity
void get_min_estimate(double *final_est, MsqError &err)
#define MSQ_HULL_TEST_ERROR
void solve2x2(double a11, double a12, double a21, double a22, double b1, double b2, double **x, MsqError &err)
ActiveSet * originalActive
void condition3x3(double **A, double *cond, MsqError &err)
void form_reduced_matrix(double ***P, MsqError &err)
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
virtual void initialize_mesh_iteration(PatchData &pd, MsqError &err)
void find_active_set(double *function, ActiveSet *active_set, MsqError &err)
void get_gradient_projections(MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
object is in an invalid state
NonSmoothSteepestDescent(ObjectiveFunction *of)
void find_plane_normal(double pt1[3], double pt2[3], double pt3[3], double *cross, MsqError &err)
CGAL_KERNEL_LARGE_INLINE PointS3< FT > projection(const PointS3< FT > &p, const PlaneS3< FT > &h)
int improvement_check(MsqError &err)
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
bool compute_function(PatchData *pd, double *function, MsqError &err)
int check_vector_dots(double **vec, int num_vec, double *normal, MsqError &err)
MsqVertex is the Mesquite object that stores information about the vertices in the mesh...
void compute_alpha(MsqError &err)
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom
#define MSQ_NORMALIZE(v, n)
virtual void optimize_vertex_positions(PatchData &pd, MsqError &err)
void init_max_step_length(MsqError &err)
void copy_active(ActiveSet *active1, ActiveSet *active2, MsqError &err)
void print_active_set(ActiveSet *active_set, double *func, MsqError &err)