Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NonSmoothSteepestDescent Class Reference

#include <NonSmoothSteepestDescent.hpp>

Inheritance diagram for NonSmoothSteepestDescent:
Collaboration diagram for NonSmoothSteepestDescent:

Public Member Functions

 NonSmoothSteepestDescent (ObjectiveFunction *of)
 
virtual ~NonSmoothSteepestDescent ()
 
 NonSmoothSteepestDescent (ObjectiveFunction *of)
 
virtual ~NonSmoothSteepestDescent ()
 
- Public Member Functions inherited from VertexMover
virtual ~VertexMover ()
 
virtual double loop_over_mesh (MeshSet &ms, MsqError &err)
 Improves the quality of the MeshSet, calling some methods specified in a class derived from VertexMover. More...
 
virtual ~VertexMover ()
 
virtual double loop_over_mesh (MeshSet &ms, MsqError &err)
 This is the "run" function of PatchDataUser. It can do anything really. More...
 
- Public Member Functions inherited from QualityImprover
virtual ~QualityImprover ()
 
void set_name (msq_std::string name)
 provides a name to the QualityImprover (use it in constructor). More...
 
virtual msq_std::string get_name ()
 retrieves the QualityImprover name. A default name should be set in the constructor. More...
 
virtual AlgorithmType get_algorithm_type ()
 Return the algorithm type (to avoid RTTI use). More...
 
void set_inner_termination_criterion (TerminationCriterion *crit)
 Sets in the termination criterion for the concrete solver's optimization. More...
 
void set_outer_termination_criterion (TerminationCriterion *crit)
 Sets in the termination criterion for the outer loop over patches. More...
 
virtual ~QualityImprover ()
 
void set_name (msq_std::string name)
 provides a name to the QualityImprover (use it in constructor). More...
 
virtual msq_std::string get_name ()
 retrieves the QualityImprover name. A default name should be set in the constructor. More...
 
virtual AlgorithmType get_algorithm_type ()
 Return the algorithm type (to avoid RTTI use). More...
 
void set_inner_termination_criterion (TerminationCriterion *crit)
 Sets in the termination criterion for the concrete solver's optimization. More...
 
void set_outer_termination_criterion (TerminationCriterion *crit)
 Sets in the termination criterion for the outer loop over patches. More...
 
- Public Member Functions inherited from PatchDataUser
virtual ~PatchDataUser ()
 
virtual void set_patch_type (PatchData::PatchType patch_type, MsqError &err, int param1=0, int param2=0)
 Sets the Patch Type. More...
 
PatchData::PatchType get_patch_type ()
 Returns the Patch Type. More...
 
int get_nb_layers (MsqError &err)
 Returns number of layers (if relevant for partition algorythm). More...
 
void add_culling_method (enum PatchData::culling_method cm)
 Sets on the culling method passed as argument. More...
 
void no_culling_method ()
 Sets off all culling methods. More...
 
void remove_culling_method (enum PatchData::culling_method cm)
 Sets off the culling method passed as argument. More...
 
long unsigned int get_culling_method_bits ()
 Returns the bitset containing culling methods flags. More...
 
void set_all_parameters (PatchDataParameters &params)
 
PatchDataParametersget_all_parameters ()
 Returns the PatchDataParameters object. More...
 
void set_global_patch (PatchData *pd, MsqError &err)
 Sets the Global Patch, so that it can be use by contiguoug PatchDataUser. More...
 
PatchDataget_global_patch ()
 Returns the Global Patch. More...
 
void no_global_patch ()
 Sets the Global Patch pointer to NULL. More...
 
virtual ~PatchDataUser ()
 
virtual void set_patch_type (PatchData::PatchType patch_type, MsqError &err, int param1=0, int param2=0)
 Sets the Patch Type. More...
 
PatchData::PatchType get_patch_type ()
 Returns the Patch Type. More...
 
int get_nb_layers (MsqError &err)
 Returns number of layers (if relevant for partition algorythm). More...
 
void add_culling_method (enum PatchData::culling_method cm)
 Sets on the culling method passed as argument. More...
 
void no_culling_method ()
 Sets off all culling methods. More...
 
void remove_culling_method (enum PatchData::culling_method cm)
 Sets off the culling method passed as argument. More...
 
long unsigned int get_culling_method_bits ()
 Returns the bitset containing culling methods flags. More...
 
void set_all_parameters (PatchDataParameters &params)
 
PatchDataParametersget_all_parameters ()
 Returns the PatchDataParameters object. More...
 
void set_global_patch (PatchData *pd, MsqError &err)
 Sets the Global Patch, so that it can be use by contiguoug PatchDataUser. More...
 
PatchDataget_global_patch ()
 Returns the Global Patch. More...
 
void no_global_patch ()
 Sets the Global Patch pointer to NULL. More...
 

Protected Member Functions

virtual void initialize (PatchData &pd, MsqError &err)
 
virtual void optimize_vertex_positions (PatchData &pd, MsqError &err)
 
virtual void initialize_mesh_iteration (PatchData &pd, MsqError &err)
 
virtual void terminate_mesh_iteration (PatchData &pd, MsqError &err)
 
virtual void cleanup ()
 
virtual void initialize (PatchData &pd, MsqError &err)
 
virtual void optimize_vertex_positions (PatchData &pd, MsqError &err)
 
virtual void initialize_mesh_iteration (PatchData &pd, MsqError &err)
 
virtual void terminate_mesh_iteration (PatchData &pd, MsqError &err)
 
virtual void cleanup ()
 
- Protected Member Functions inherited from VertexMover
 VertexMover ()
 
size_t check_feasible (PatchData &pd, MsqError &err)
 CHECK FEASIBLE IS NOT YET IMPLEMENTED. More...
 
 VertexMover ()
 
size_t check_feasible (PatchData &pd, MsqError &err)
 CHECK FEASIBLE IS NOT YET IMPLEMENTED. More...
 
- Protected Member Functions inherited from QualityImprover
 QualityImprover ()
 
const MeshSetget_mesh_set () const
 
MeshSetget_mesh_set ()
 
void set_mesh_set (MeshSet *ms)
 
TerminationCriterionget_outer_termination_criterion ()
 return the outer termination criterion pointer More...
 
TerminationCriterionget_inner_termination_criterion ()
 return the inner termination criterion pointer More...
 
 QualityImprover ()
 
const MeshSetget_mesh_set () const
 
MeshSetget_mesh_set ()
 
void set_mesh_set (MeshSet *ms)
 
TerminationCriterionget_outer_termination_criterion ()
 return the outer termination criterion pointer More...
 
TerminationCriterionget_inner_termination_criterion ()
 return the inner termination criterion pointer More...
 
- Protected Member Functions inherited from PatchDataUser
 PatchDataUser ()
 
 PatchDataUser ()
 

Private Member Functions

void init_opt (MsqError &err)
 
void init_max_step_length (MsqError &err)
 
void minmax_opt (PatchData &pd, MsqError &err)
 
void step_acceptance (PatchData &pd, MsqError &err)
 
void get_min_estimate (double *final_est, MsqError &err)
 
void get_gradient_projections (MsqError &err)
 
void compute_alpha (MsqError &err)
 
void copy_active (ActiveSet *active1, ActiveSet *active2, MsqError &err)
 
bool compute_function (PatchData *pd, double *function, MsqError &err)
 
double ** compute_gradient (PatchData *pd, MsqError &err)
 
void find_active_set (double *function, ActiveSet *active_set, MsqError &err)
 
void print_active_set (ActiveSet *active_set, double *func, MsqError &err)
 
int improvement_check (MsqError &err)
 
int validity_check (MsqError &err)
 
void check_equilibrium (int *equil, int *opt_status, MsqError &err)
 
int convex_hull_test (double **vec, int num_vec, MsqError &err)
 
int check_vector_dots (double **vec, int num_vec, double *normal, MsqError &err)
 
void find_plane_normal (double pt1[3], double pt2[3], double pt3[3], double *cross, MsqError &err)
 
void find_plane_points (int dir1, int dir2, double **vec, int num_vec, double *pt1, double *pt2, double *pt3, int *opt_status, MsqError &err)
 
void form_grammian (double **vec, MsqError &err)
 
void form_PD_grammian (MsqError &err)
 
void singular_test (int n, double **A, int *singular, MsqError &err)
 
void condition3x3 (double **A, double *cond, MsqError &err)
 
void solve2x2 (double a11, double a12, double a21, double a22, double b1, double b2, double **x, MsqError &err)
 
void form_reduced_matrix (double ***P, MsqError &err)
 
void search_direction (PatchData &pd, MsqError &err)
 
void search_edges_faces (double **dir, MsqError &err)
 
void get_active_directions (double **gradient, double ***dir, MsqError &err)
 
void init_opt (MsqError &err)
 
void init_max_step_length (MsqError &err)
 
void minmax_opt (PatchData &pd, MsqError &err)
 
void step_acceptance (PatchData &pd, MsqError &err)
 
void get_min_estimate (double *final_est, MsqError &err)
 
void get_gradient_projections (MsqError &err)
 
void compute_alpha (MsqError &err)
 
void copy_active (ActiveSet *active1, ActiveSet *active2, MsqError &err)
 
bool compute_function (PatchData *pd, double *function, MsqError &err)
 
double ** compute_gradient (PatchData *pd, MsqError &err)
 
void find_active_set (double *function, ActiveSet *active_set, MsqError &err)
 
void print_active_set (ActiveSet *active_set, double *func, MsqError &err)
 
int improvement_check (MsqError &err)
 
int validity_check (MsqError &err)
 
void check_equilibrium (int *equil, int *opt_status, MsqError &err)
 
int convex_hull_test (double **vec, int num_vec, MsqError &err)
 
int check_vector_dots (double **vec, int num_vec, double *normal, MsqError &err)
 
void find_plane_normal (double pt1[3], double pt2[3], double pt3[3], double *cross, MsqError &err)
 
void find_plane_points (int dir1, int dir2, double **vec, int num_vec, double *pt1, double *pt2, double *pt3, int *opt_status, MsqError &err)
 
void form_grammian (double **vec, MsqError &err)
 
void form_PD_grammian (MsqError &err)
 
void singular_test (int n, double **A, int *singular, MsqError &err)
 
void condition3x3 (double **A, double *cond, MsqError &err)
 
void solve2x2 (double a11, double a12, double a21, double a22, double b1, double b2, double **x, MsqError &err)
 
void form_reduced_matrix (double ***P, MsqError &err)
 
void search_direction (PatchData &pd, MsqError &err)
 
void search_edges_faces (double **dir, MsqError &err)
 
void get_active_directions (double **gradient, double ***dir, MsqError &err)
 

Private Attributes

int mDimension
 
int numVertices
 
int numElements
 
MsqVertexmCoords
 
MsqMeshEntitymConnectivity
 
int numFree
 
int freeVertexIndex
 
double activeEpsilon
 
double minAcceptableImprovement
 
double minStepSize
 
double originalValue
 
int iterCount
 
int optIterCount
 
int numFunctionValues
 
double * mFunction
 
double * testFunction
 
double * originalFunction
 
double ** mGradient
 
int optStatus
 
int equilibriumPt
 
int mSteepest
 
double mSearch [3]
 
double mAlpha
 
double maxAlpha
 
double * mGS
 
double * prevActiveValues
 
double ** mG
 
double ** mPDG
 
int pdgInd [3]
 
ActiveSetmActive
 
ActiveSettestActive
 
ActiveSetoriginalActive
 

Additional Inherited Members

- Public Types inherited from PatchDataUser
enum  AlgorithmType {
  QUALITY_IMPROVER, QUALITY_ASSESSOR, MESH_TRANSFORM, TARGET_CALCULATOR,
  QUALITY_IMPROVER, QUALITY_ASSESSOR, MESH_TRANSFORM, TARGET_CALCULATOR
}
 
enum  AlgorithmType {
  QUALITY_IMPROVER, QUALITY_ASSESSOR, MESH_TRANSFORM, TARGET_CALCULATOR,
  QUALITY_IMPROVER, QUALITY_ASSESSOR, MESH_TRANSFORM, TARGET_CALCULATOR
}
 
- Protected Attributes inherited from VertexMover
ObjectiveFunctionobjFunc
 

Detailed Description

Definition at line 145 of file includeLinks/NonSmoothSteepestDescent.hpp.

Constructor & Destructor Documentation

Definition at line 45 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References i, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mGradient, NonSmoothSteepestDescent::mGS, NonSmoothSteepestDescent::mPDG, MSQ_DBGOUT, VertexMover::objFunc, NonSmoothSteepestDescent::originalActive, NonSmoothSteepestDescent::originalFunction, NonSmoothSteepestDescent::prevActiveValues, QualityImprover::set_name(), NonSmoothSteepestDescent::testActive, and NonSmoothSteepestDescent::testFunction.

46 {
47  objFunc=of;
48  this->set_name("NonSmoothSteepestDescent");
49 
50  mFunction = (double *)malloc(sizeof(double)*150);
51  testFunction = (double *)malloc(sizeof(double)*150);
52  originalFunction = (double *)malloc(sizeof(double)*150);
53  mGradient = (double **)malloc(sizeof(double *)*150);
54  mGS = (double *)malloc(sizeof(double)*150);
55  mG = (double **)malloc(sizeof(double *)*150);
56  mPDG = (double **)malloc(sizeof(double *)*3);
57  prevActiveValues=(double *)malloc(sizeof(double)*150);
58 
59  int i;
60  for (i=0;i<150;i++) {
61  mGradient[i] = (double *)malloc(sizeof(double)*3);
62  mG[i] = (double *)malloc(sizeof(double)*150);
63  }
64  for (i=0;i<3;i++) mPDG[i] = (double *)malloc(sizeof(double)*3);
65 
66  mActive = (ActiveSet *)malloc(sizeof(ActiveSet));
67  testActive = (ActiveSet *)malloc(sizeof(ActiveSet));
68  originalActive = (ActiveSet *)malloc(sizeof(ActiveSet));
69  MSQ_DBGOUT(1) << "- Executed NonSmoothSteepestDescent::NonSmoothSteepestDescent()\n";
70 }
void set_name(msq_std::string name)
provides a name to the QualityImprover (use it in constructor).
blockLoc i
Definition: read.cpp:79
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.

Here is the call graph for this function:

virtual ~NonSmoothSteepestDescent ( )
inlinevirtual

Definition at line 150 of file includeLinks/NonSmoothSteepestDescent.hpp.

150 { }

Member Function Documentation

void check_equilibrium ( int *  equil,
int *  opt_status,
MsqError err 
)
inlineprivate

Definition at line 658 of file includeLinks/NonSmoothSteepestDescent.hpp.

References NonSmoothSteepestDescent::convex_hull_test(), NonSmoothSteepestDescent::form_grammian(), NonSmoothSteepestDescent::get_active_directions(), i, j, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mGradient, min(), MSQ_DOT, MSQ_EQUILIBRIUM, MSQ_FALSE, MSQ_MACHINE_EPS, MSQ_NORMALIZE, MSQ_PRINT, ActiveSet::num_active, and NonSmoothSteepestDescent::numFunctionValues.

Referenced by NonSmoothSteepestDescent::minmax_opt().

659 {
660 // int ierr;
661  int i,j;
662  int ind1, ind2;
663  double min;
664  double **dir;
665  double mid_vec[3], mid_cos, test_cos;
666 
667  //TODO - this subroutine is no longer clear to me... is it still
668  // appropriate for quads and hexes? I think it might be in 2D, but
669  // 3D is less clear. Is there a more general algorithm to use?
670  // ask Todd/check in numerical optimization
671 
672  *equil = MSQ_FALSE;
673  ind1 = ind2 = -1;
674 
675  int num_active = mActive->num_active;
676 
677  if (num_active==numFunctionValues)
678  {
679  *equil = 1; *status = MSQ_EQUILIBRIUM;
680  MSQ_PRINT(3)("All the function values are in the active set\n");
681  }
682 
683  /* set up the active mGradient directions */
684  this->get_active_directions(mGradient,&dir,err);
685 
686  /* normalize the active directions */
687  for (j=0;j<num_active;j++) MSQ_NORMALIZE(dir[j],mDimension);
688 
689  if (mDimension == 2) {
690  /* form the grammian */
691  this->form_grammian(dir,err);
692 
693  /* find the minimum element in the upper triangular portion of G*/
694  min = 1;
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 ) {
698  *equil = 1; *status = MSQ_EQUILIBRIUM;
699  MSQ_PRINT(3)("The gradients are antiparallel, eq. pt\n");
700  }
701  if (mG[i][j] < min) {
702  ind1 = i; ind2 = j;
703  min = mG[i][j];
704  }
705  }
706  }
707 
708  if ((ind1 != -1) && (ind2 != -1)) {
709  /* find the diagonal of the parallelepiped */
710  for (j=0;j<mDimension;j++) {
711  mid_vec[j]=.5*(dir[ind1][j]+dir[ind2][j]);
712  }
713  MSQ_NORMALIZE(mid_vec,mDimension);
714  MSQ_DOT(mid_cos,dir[ind1],mid_vec,mDimension);
715 
716  /* test the other vectors to be sure they lie in the cone */
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) {
721  MSQ_PRINT(3)("An equilibrium point \n");
722  *equil = 1; *status = MSQ_EQUILIBRIUM;
723  }
724  }
725  }
726  }
727  }
728  if (mDimension == 3) {
729  *equil = this->convex_hull_test(dir,num_active,err);
730  if (*equil == 1) *status = MSQ_EQUILIBRIUM;
731  }
732 }
int convex_hull_test(double **vec, int num_vec, MsqError &err)
void get_active_directions(double **gradient, double ***dir, MsqError &err)
blockLoc i
Definition: read.cpp:79
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
j indices j
Definition: Indexing.h:6
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.

Here is the call graph for this function:

Here is the caller graph for this function:

void check_equilibrium ( int *  equil,
int *  opt_status,
MsqError err 
)
private
int check_vector_dots ( double **  vec,
int  num_vec,
double *  normal,
MsqError err 
)
inlineprivate

Definition at line 517 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, MSQ_DOT, MSQ_FALSE, MSQ_MACHINE_EPS, and MSQ_TRUE.

Referenced by NonSmoothSteepestDescent::convex_hull_test().

521 {
522  int equil;
523  int i, ind;
524  double test_dot, dot;
525 
526  equil = MSQ_FALSE;
527  MSQ_DOT(test_dot,vec[0],normal,3);
528  ind = 1;
529  while ((fabs(test_dot) < MSQ_MACHINE_EPS) && (ind<num_vec)) {
530  MSQ_DOT(test_dot,vec[ind],normal,3);
531  ind++;
532  }
533 
534  for (i=ind;i<num_vec;i++) {
535  MSQ_DOT(dot,vec[i],normal,3);
536  if ( ((dot>0 && test_dot<0) || (dot<0 && test_dot>0)) &&
537  (fabs(dot)>MSQ_MACHINE_EPS)) {
538  return(equil = MSQ_TRUE);
539 
540  }
541  }
542  return(equil);
543 }
blockLoc i
Definition: read.cpp:79

Here is the caller graph for this function:

int check_vector_dots ( double **  vec,
int  num_vec,
double *  normal,
MsqError err 
)
private
virtual void cleanup ( )
protectedvirtual

Implements VertexMover.

void cleanup ( )
protectedvirtual

Implements VertexMover.

Definition at line 169 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References i, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mGradient, NonSmoothSteepestDescent::mGS, NonSmoothSteepestDescent::mPDG, MSQ_DBGOUT, NonSmoothSteepestDescent::originalActive, NonSmoothSteepestDescent::originalFunction, NonSmoothSteepestDescent::prevActiveValues, NonSmoothSteepestDescent::testActive, and NonSmoothSteepestDescent::testFunction.

170 {
171  MSQ_DBGOUT(1) << "- Executing NonSmoothSteepestDescent::cleanup()\n";
172  int i;
173  for (i=0;i<150;i++) {
174  free(mGradient[i]);
175  free(mG[i]);
176  }
177  for (i=0;i<3;i++) free(mPDG[i]);
178 
179  free(mFunction);
180  free(testFunction);
181  free(originalFunction);
182  free(mGradient);
183  free(mGS);
184  free(mG);
185  free(mPDG);
186  free(prevActiveValues);
187  free(mActive);
188  free(testActive);
189  free(originalActive);
190  MSQ_DBGOUT(1) << "- Done with NonSmoothSteepestDescent::cleanup()\n";
191 }
blockLoc i
Definition: read.cpp:79
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
void compute_alpha ( MsqError err)
private
void compute_alpha ( MsqError err)
inlineprivate

Definition at line 1025 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, NonSmoothSteepestDescent::mAlpha, NonSmoothSteepestDescent::maxAlpha, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mGS, NonSmoothSteepestDescent::minStepSize, MSQ_PRINT, NonSmoothSteepestDescent::mSteepest, and NonSmoothSteepestDescent::numFunctionValues.

Referenced by NonSmoothSteepestDescent::minmax_opt().

1026 {
1027 // int ierr;
1028 // int j;
1029  int i;
1030 // int ind;
1031  int num_values;
1032  double steepest_function;
1033  double steepest_grad;
1034  double alpha_i;
1035  double min_positive_value=1E300;
1036 
1037 // FUNCTION_TIMER_START("Compute Alpha");
1038 
1039  MSQ_PRINT(2)("In compute alpha\n");
1040 
1041  num_values = numFunctionValues;
1042  mAlpha = 1E300;
1043 
1044  steepest_function = mFunction[mSteepest];
1045  steepest_grad = mGS[mSteepest];
1046  for (i=0;i<num_values;i++)
1047  {
1048  /* if it's not active */
1049  if (i!=mSteepest)
1050  {
1051  alpha_i = steepest_function - mFunction[i];
1052 
1053  if (fabs(mGS[mSteepest] - mGS[i])>1E-13) {
1054  /* compute line intersection */
1055  alpha_i = alpha_i/(steepest_grad - mGS[i]);
1056  } else {
1057  /* the lines don't intersect - it's not under consideration*/
1058  alpha_i = 0;
1059  }
1060  if ((alpha_i > minStepSize ) && (fabs(alpha_i) < fabs(mAlpha))) {
1061  mAlpha = fabs(alpha_i);
1062  MSQ_PRINT(3)("Setting alpha %d %g\n",i,alpha_i);
1063  }
1064  if ((alpha_i > 0) && (alpha_i < min_positive_value)) {
1065  min_positive_value = alpha_i;
1066  }
1067  }
1068  }
1069 
1070  if ((mAlpha == 1E300) && (min_positive_value != 1E300)) {
1071  mAlpha = min_positive_value;
1072  }
1073 
1074  /* if it never gets set, set it to the default */
1075  if (mAlpha == 1E300) {
1076  mAlpha = maxAlpha;
1077  MSQ_PRINT(3)("Setting alpha to the maximum step length\n");
1078  }
1079 
1080  MSQ_PRINT(3)(" The initial step size: %f\n",mAlpha);
1081 
1082 // FUNCTION_TIMER_END();
1083 }
blockLoc i
Definition: read.cpp:79
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.

Here is the caller graph for this function:

bool compute_function ( PatchData pd,
double *  function,
MsqError err 
)
private
bool compute_function ( PatchData pd,
double *  function,
MsqError err 
)
inlineprivate

Definition at line 248 of file includeLinks/NonSmoothSteepestDescent.hpp.

References PatchData::element_by_index(), QualityMetric::evaluate_element(), ObjectiveFunction::get_quality_metric(), ObjectiveFunction::get_quality_metric_list(), i, MSQ_ERRZERO, NonSmoothSteepestDescent::numElements, and VertexMover::objFunc.

Referenced by NonSmoothSteepestDescent::compute_gradient(), NonSmoothSteepestDescent::optimize_vertex_positions(), and NonSmoothSteepestDescent::step_acceptance().

249 {
250  // ASSUMES ONE VALUE PER ELEMENT; ALSO NEED 1.0/FUNCTION WHICH IS ONLY
251  // TRUE OF CONDITION NUMBER
252 
253  // MSQ_DEBUG_PRINT(2,"Computing Function\n");
254 // FUNCTION_TIMER_START("Compute Function");
255 
256  //TODO need to switch this to element or vertex metric evaluations
257  //TODO need to include boolean testing for validity
258  int i;
259  bool valid_bool=true;
260 
261  for (i=0;i<numElements;i++) func[i]=0.0;
262  QualityMetric* currentQM=objFunc->get_quality_metric();
263  if(currentQM==NULL){
264  currentQM = objFunc->get_quality_metric_list().front();
265  }
266 
267  for (i=0;i<numElements;i++) {
268  valid_bool = currentQM->evaluate_element(*patch_data,
269  &(patch_data->element_by_index(i)),
270  func[i], err); MSQ_ERRZERO(err);
271  // MSQ_DEBUG_ACTION(3,{fprintf(stdout," Function value[%d]=%g\n",i,func[i]);});
272  }
273 // FUNCTION_TIMER_END();
274  return(valid_bool);
275 }
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
virtual msq_std::list< QualityMetric * > get_quality_metric_list()
blockLoc i
Definition: read.cpp:79

Here is the call graph for this function:

Here is the caller graph for this function:

double** compute_gradient ( PatchData pd,
MsqError err 
)
private
double ** compute_gradient ( PatchData pd,
MsqError err 
)
inlineprivate

Definition at line 278 of file includeLinks/NonSmoothSteepestDescent.hpp.

References NonSmoothSteepestDescent::compute_function(), NonSmoothSteepestDescent::freeVertexIndex, ObjectiveFunction::get_quality_metric(), ObjectiveFunction::get_quality_metric_list(), i, j, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mGradient, MSQ_CHKERR, MSQ_DBGOUT, NonSmoothSteepestDescent::numElements, NonSmoothSteepestDescent::numFunctionValues, and VertexMover::objFunc.

Referenced by NonSmoothSteepestDescent::minmax_opt().

279 {
280 // FUNCTION_TIMER_START("Compute Gradient");
281 
282  MSQ_DBGOUT(2) << "Computing Gradient\n";
283 
284  double delta = 10e-6;
285 
286  for (int i=0;i<numElements;i++) {
287  for (int j=0;j<3;j++) mGradient[i][j] = 0.0;
288  }
289  QualityMetric* currentQM=objFunc->get_quality_metric();
290  if(currentQM==NULL)
291  currentQM = objFunc->get_quality_metric_list().front();
292 
293  double *func, *fdelta;
294  func = (double *)malloc(sizeof(double)*150);
295  fdelta = (double *)malloc(sizeof(double)*150);
296 
297  this->compute_function(patch_data, func, err);
298  if (MSQ_CHKERR(err)) {
299  free(func);
300  free(fdelta);
301  return 0;
302  }
303 
304  /* gradient in the x, y, z direction */
305 
306  for (int j=0;j<3;j++) {
307 
308  // perturb the coordinates of the free vertex in the j direction by delta
309  mCoords[freeVertexIndex][j] += delta;
310 
311  //compute the function at the perturbed point location
312  this->compute_function(patch_data, fdelta, err);
313  if (MSQ_CHKERR(err)) {
314  free(func);
315  free(fdelta);
316  return 0;
317  }
318 
319  //compute the numerical gradient
320  for (int i=0;i<numFunctionValues;i++) {
321  mGradient[i][j] = (fdelta[i] - func[i])/delta;
322  // MSQ_DEBUG_ACTION(3,{fprintf(stdout," Gradient value[%d][%d]=%g\n",i,j,mGradient[i][j]);});
323  }
324 
325  // put the coordinates back where they belong
326  mCoords[freeVertexIndex][j] -= delta;
327  }
328 
329  free(func);
330  free(fdelta);
331 // FUNCTION_TIMER_END();
332  return(mGradient);
333 }
virtual msq_std::list< QualityMetric * > get_quality_metric_list()
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
bool compute_function(PatchData *pd, double *function, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

void condition3x3 ( double **  A,
double *  cond,
MsqError err 
)
inlineprivate

Definition at line 736 of file includeLinks/NonSmoothSteepestDescent.hpp.

References denom, MSQ_FALSE, MSQ_MACHINE_EPS, MSQ_TRUE, and sqrt().

Referenced by NonSmoothSteepestDescent::singular_test().

738 {
739 // int ierr;
740  double a11, a12, a13;
741  double a21, a22, a23;
742  double a31, a32, a33;
743 // double s1, s2, s4, s3, t0;
744  double s1, s2, s3;
745  double denom;
746 // double one = 1.0;
747  double temp;
748  int zero_denom = MSQ_TRUE;
749 
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];
753 
754  denom = -a11*a22*a33+a11*a23*a32+a21*a12*a33-a21*a13*a32-
755  a31*a12*a23+a31*a13*a22;
756 
757  if ( (fabs(a11) > MSQ_MACHINE_EPS) &&
758  (fabs(denom/a11) > MSQ_MACHINE_EPS)) {
759  zero_denom = MSQ_FALSE;
760  }
761  if ( (fabs(a22) > MSQ_MACHINE_EPS) &&
762  (fabs(denom/a22) > MSQ_MACHINE_EPS)) {
763  zero_denom = MSQ_FALSE;
764  }
765  if ( (fabs(a33) > MSQ_MACHINE_EPS) &&
766  (fabs(denom/a33) > MSQ_MACHINE_EPS)) {
767  zero_denom = MSQ_FALSE;
768  }
769 
770  if (zero_denom) {
771  (*cond) = 1E300;
772  } else {
773  s1 = sqrt(a11*a11 + a12*a12 + a13*a13 +
774  a21*a21 + a22*a22 + a23*a23 +
775  a31*a31 + a32*a32 + a33*a33);
776 
777  temp = (-a22*a33+a23*a32)/denom;
778  s3 = temp*temp;
779  temp =(a12*a33-a13*a32)/denom;
780  s3 += temp*temp;
781  temp = (a12*a23-a13*a22)/denom;
782  s3 += temp*temp;
783  temp = (a21*a33-a23*a31)/denom;
784  s3 += temp*temp;
785  temp = (a11*a33-a13*a31)/denom;
786  s3 += temp*temp;
787  temp = (a11*a23-a13*a21)/denom;
788  s3 += temp*temp;
789  temp = (a21*a32-a22*a31)/denom;
790  s3 += temp*temp;
791  temp = (-a11*a32+a12*a31)/denom;
792  s3 += temp*temp;
793  temp = (-a11*a22+a12*a21)/denom;
794  s3 += temp*temp;
795 
796  s2 = sqrt(s3);
797  (*cond) = s1*s2;
798  }
799 }
double sqrt(double d)
Definition: double.h:73
rational * A
Definition: vinci_lass.c:67
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom

Here is the call graph for this function:

Here is the caller graph for this function:

void condition3x3 ( double **  A,
double *  cond,
MsqError err 
)
private
int convex_hull_test ( double **  vec,
int  num_vec,
MsqError err 
)
inlineprivate

Definition at line 566 of file includeLinks/NonSmoothSteepestDescent.hpp.

References NonSmoothSteepestDescent::check_vector_dots(), NonSmoothSteepestDescent::find_plane_normal(), NonSmoothSteepestDescent::find_plane_points(), MsqError::INVALID_STATE, MSQ_CHECK_X_COORD_DIRECTION, MSQ_CHECK_Y_COORD_DIRECTION, MSQ_CHECK_Z_COORD_DIRECTION, MSQ_EQUIL, MSQ_HULL_TEST_ERROR, MSQ_NO_EQUIL, MSQ_PRINT, MSQ_SETERR, MSQ_THREE_PT_PLANE, MSQ_TWO_PT_PLANE, MSQ_XDIR, MSQ_YDIR, and MSQ_ZDIR.

Referenced by NonSmoothSteepestDescent::check_equilibrium().

567 {
568 // int ierr;
569  int equil;
570  int status, dir_done;
571  double pt1[3], pt2[3], pt3[3];
572  double normal[3];
573 
574 // FUNCTION_TIMER_START("Convex Hull Test");
575  /* tries to determine equilibrium for the 3D case */
576  equil = 0;
578  dir_done = -1;
579 
580  if (num_vec <= 2) status = MSQ_NO_EQUIL;
581 
582  while ((status != MSQ_EQUIL) && (status != MSQ_NO_EQUIL) &&
583  (status != MSQ_HULL_TEST_ERROR)) {
584  if (status == MSQ_CHECK_Z_COORD_DIRECTION) {
586  vec, num_vec, pt1, pt2, pt3, &status, err);
587  dir_done = 2;
588  }
589  if (status == MSQ_CHECK_Y_COORD_DIRECTION) {
591  vec, num_vec, pt1, pt2, pt3, &status, err);
592  dir_done = 1;
593  }
594  if (status == MSQ_CHECK_X_COORD_DIRECTION) {
596  vec, num_vec, pt1, pt2, pt3, &status, err);
597  dir_done = 0;
598  }
599  if (status == MSQ_TWO_PT_PLANE) {
600  pt3[0]=0.; pt3[1]=0.; pt3[2]=0.;
601  }
602  if ((status == MSQ_TWO_PT_PLANE) || (status == MSQ_THREE_PT_PLANE)){
603  this->find_plane_normal(pt1,pt2,pt3,normal,err);
604  equil = this->check_vector_dots(vec,num_vec,normal,err);
605  if (equil == 1) {
606  switch(dir_done){
607  case 2:
608  equil = 0; status = MSQ_CHECK_Y_COORD_DIRECTION;
609  break;
610  case 1:
611  equil = 0; status = MSQ_CHECK_X_COORD_DIRECTION;
612  break;
613  case 0:
614  equil = 1; status = MSQ_EQUIL;
615  }
616  } else if (equil == 0) {
617  status = MSQ_NO_EQUIL;
618  } else {
619  MSQ_SETERR(err)("equil flag not set to 0 or 1",MsqError::INVALID_STATE);
620  }
621  }
622  }
623  switch (status){
624  case MSQ_NO_EQUIL:
625  MSQ_PRINT(3)("Not an equilibrium point\n");
626  equil = 0;
627  break;
628  case MSQ_EQUIL:
629  MSQ_PRINT(3)("An equilibrium point\n");
630  equil = 1;
631  break;
632  default:
633  MSQ_PRINT(3)("Failed to determine equil or not; status = %d\n",status);
634  }
635 // FUNCTION_TIMER_END();
636  return (equil);
637 }
void find_plane_points(int dir1, int dir2, double **vec, int num_vec, double *pt1, double *pt2, double *pt3, int *opt_status, MsqError &err)
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
object is in an invalid state
void find_plane_normal(double pt1[3], double pt2[3], double pt3[3], double *cross, MsqError &err)
int check_vector_dots(double **vec, int num_vec, double *normal, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

int convex_hull_test ( double **  vec,
int  num_vec,
MsqError err 
)
private
void copy_active ( ActiveSet active1,
ActiveSet active2,
MsqError err 
)
private
void copy_active ( ActiveSet active1,
ActiveSet active2,
MsqError err 
)
inlineprivate

Definition at line 1086 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, i, MsqError::INVALID_ARG, MSQ_SETERR, ActiveSet::num_active, ActiveSet::num_equal, and ActiveSet::true_active_value.

Referenced by NonSmoothSteepestDescent::step_acceptance().

1088 {
1089  if (active1==NULL || active2==NULL) {
1090  MSQ_SETERR(err)("Null memory in copy_active\n",MsqError::INVALID_ARG);
1091  return;
1092  }
1093 
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];
1099  }
1100 }
invalid function argument passed
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79

Here is the caller graph for this function:

void find_active_set ( double *  function,
ActiveSet active_set,
MsqError err 
)
inlineprivate

Definition at line 335 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, NonSmoothSteepestDescent::activeEpsilon, for(), i, MSQ_DBGOUT, MSQ_MACHINE_EPS, Mesquite::MSQ_MAX, ActiveSet::num_active, ActiveSet::num_equal, NonSmoothSteepestDescent::numFunctionValues, and ActiveSet::true_active_value.

Referenced by NonSmoothSteepestDescent::minmax_opt(), NonSmoothSteepestDescent::optimize_vertex_positions(), and NonSmoothSteepestDescent::step_acceptance().

338 {
339  int i, ind;
340  double function_val;
341  double active_value0;
342  double temp;
343 
344 // FUNCTION_TIMER_START("Find Active Set");
345  MSQ_DBGOUT(2) << "\nFinding the active set\n";
346 
347  // initialize the active set indices to zero
348  for (i=0;i<numFunctionValues;i++) active_set->active_ind[i] = 0;
349 
350  /* the first function value is our initial active value */
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];
355  // MSQ_DEBUG_ACTION(3,{fprintf(stdout," function value[0]: %g\n",function[0]);});
356 
357  /* first sort out the active set...
358  all vals within active_epsilon of largest val */
359 
360  for (i=1;i<numFunctionValues;i++) {
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);
365  // MSQ_DEBUG_ACTION(3,{fprintf(stdout," function value[%d]: %g\n",i,function[i]);});
366  if ( function_val > active_value0 ) {
367  if ( temp > activeEpsilon) {
368  active_set->num_active = 1;
369  active_set->num_equal = 0;
370  active_set->active_ind[0] = i;
371  } else if ( temp < activeEpsilon) {
372  active_set->num_active += 1;
373  ind = active_set->num_active - 1;
374  active_set->active_ind[ind] = i;
375  if (fabs(function_val - active_value0) < MSQ_MACHINE_EPS) {
376  active_set->num_equal += 1;
377  }
378  }
379  } else {
380  if (temp < activeEpsilon) {
381  active_set->num_active += 1;
382  ind = active_set->num_active - 1;
383  active_set->active_ind[ind] = i;
384  if (fabs(function_val - active_value0) < MSQ_MACHINE_EPS) {
385  active_set->num_equal += 1;
386  }
387  }
388  }
389  }
390 
391 }
const double MSQ_MAX
Definition: Mesquite.hpp:172
blockLoc i
Definition: read.cpp:79
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
for(;;)

Here is the call graph for this function:

Here is the caller graph for this function:

void find_active_set ( double *  function,
ActiveSet active_set,
MsqError err 
)
private
void find_plane_normal ( double  pt1[3],
double  pt2[3],
double  pt3[3],
double *  cross,
MsqError err 
)
inlineprivate

Definition at line 546 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, and MSQ_NORMALIZE.

Referenced by NonSmoothSteepestDescent::convex_hull_test().

551 {
552  int i;
553  double vecA[3], vecB[3];
554 
555  for (i=0;i<3;i++) {
556  vecA[i] = pt2[i] - pt1[i];
557  vecB[i] = pt3[i] - pt1[i];
558  }
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];
562  MSQ_NORMALIZE(cross, 3);
563 }
NVec< 3, T > cross(const NVec< 3, T > &u, const NVec< 3, T > &v)
blockLoc i
Definition: read.cpp:79

Here is the caller graph for this function:

void find_plane_normal ( double  pt1[3],
double  pt2[3],
double  pt3[3],
double *  cross,
MsqError err 
)
private
void find_plane_points ( int  dir1,
int  dir2,
double **  vec,
int  num_vec,
double *  pt1,
double *  pt2,
double *  pt3,
int *  opt_status,
MsqError err 
)
private

Definition at line 213 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References i, max(), min(), MSQ_BIG_NEG_NMBR, MSQ_BIG_POS_NMBR, MSQ_CCW, MSQ_CHECK_BOTTOM_UP, MSQ_CHECK_TOP_DOWN, MSQ_CHECK_X_COORD_DIRECTION, MSQ_CHECK_Y_COORD_DIRECTION, MSQ_COPY_VECTOR, MSQ_CW, MSQ_EQUIL, MSQ_HULL_TEST_ERROR, MSQ_MACHINE_EPS, MSQ_NO_EQUIL, MSQ_PRINT, and MSQ_TWO_PT_PLANE.

Referenced by NonSmoothSteepestDescent::convex_hull_test().

218 {
219  int i;
220  int ind[50], num_min, num_max;
221  int rotate=MSQ_CW;
222  int num_rotated=0;
223  double pt_1, pt_2;
224  double min, inv_slope;
225  double min_inv_slope=0.;
226  double max;
227  double max_inv_slope=0;
228  double inv_origin_slope=0;
229 
230  *status = MSQ_CHECK_BOTTOM_UP;
231  /* find the minimum points in dir1 starting at -1 */
232  num_min = 0; ind[0]=-1; ind[1]=-1; ind[2]=-1; min=1.0;
233  for (i=0;i<num_vec;i++) {
234  if (vec[i][dir1]<min) {
235  min = vec[i][dir1]; ind[0] = i; num_min = 1;
236  } else if (fabs(vec[i][dir1] - min) < MSQ_MACHINE_EPS) {
237  ind[num_min++] = i;
238  }
239  }
240  if (min >= 0) *status = MSQ_NO_EQUIL;
241 
242  if (*status != MSQ_NO_EQUIL) {
243  switch(num_min) {
244  case 1: /* rotate to find the next point */
245  MSQ_COPY_VECTOR(pt1,vec[ind[0]],3);
246  pt_1 = pt1[dir1]; pt_2 = pt1[dir2];
247  if (pt1[dir2] <= 0){rotate=MSQ_CCW; max_inv_slope=MSQ_BIG_NEG_NMBR;}
248  if (pt1[dir2] > 0){rotate=MSQ_CW; min_inv_slope=MSQ_BIG_POS_NMBR;}
249  switch(rotate) {
250  case MSQ_CCW:
251  for (i=0;i<num_vec;i++) {
252  if (i!=ind[0]) {
253  inv_slope = (vec[i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
254  if ((inv_slope>max_inv_slope) &&
255  (fabs(inv_slope - max_inv_slope) > MSQ_MACHINE_EPS)) {
256  ind[1] = i; max_inv_slope=inv_slope; num_rotated = 1;
257  } else if (fabs(inv_slope - max_inv_slope) < MSQ_MACHINE_EPS) {
258  ind[2] = i; num_rotated++;
259  }
260  }
261  }
262  break;
263  case MSQ_CW:
264  for (i=0;i<num_vec;i++) {
265  if (i!=ind[0]) {
266  inv_slope = (vec[i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
267  if ((inv_slope<min_inv_slope) &&
268  (fabs(inv_slope - max_inv_slope) > MSQ_MACHINE_EPS)){
269  ind[1] = i; min_inv_slope=inv_slope; num_rotated = 1;
270  } else if (fabs(inv_slope - min_inv_slope) < MSQ_MACHINE_EPS) {
271  ind[2] = i; num_rotated++;
272  }
273  }
274  }
275  }
276  switch(num_rotated) {
277  case 0:
278  MSQ_PRINT(3)("No points in the rotation ... odd\n");
279  *status = MSQ_HULL_TEST_ERROR;
280  break;
281  case 1:
282  MSQ_PRINT(3)("Found a line in the convex hull\n");
283  MSQ_COPY_VECTOR(pt2,vec[ind[1]],3); *status = MSQ_TWO_PT_PLANE;
284  break;
285  default:
286  MSQ_PRINT(3)("Found 2 or more points in the rotation\n");
287  if (fabs(pt_1) > MSQ_MACHINE_EPS) inv_origin_slope = pt_2/pt_1;
288  switch(rotate) {
289  case MSQ_CCW:
290  if (inv_origin_slope >= max_inv_slope) *status=MSQ_NO_EQUIL;
291  else *status=MSQ_CHECK_TOP_DOWN;
292  break;
293  case MSQ_CW:
294  if (inv_origin_slope <= min_inv_slope) *status=MSQ_NO_EQUIL;
295  else *status=MSQ_CHECK_TOP_DOWN;
296  }
297  }
298  break;
299  case 2: /* use these two points to define the plane */
300  MSQ_PRINT(3)("Found two minimum points to define the plane\n");
301  MSQ_COPY_VECTOR(pt1,vec[ind[0]],3);
302  MSQ_COPY_VECTOR(pt2,vec[ind[1]],3);
303  *status = MSQ_TWO_PT_PLANE;
304  break;
305  default: /* check to see if all > 0 */
306  MSQ_PRINT(3)("Found 3 or more points in min plane %f\n",min);
307  if (vec[ind[0]][dir1] >= 0) *status = MSQ_NO_EQUIL;
308  else *status = MSQ_CHECK_TOP_DOWN;
309  }
310  }
311 
312  /***************************/
313  /* failed to find any information, checking top/down this coord*/
314  /***************************/
315 
316  if (*status == MSQ_CHECK_TOP_DOWN) {
317  /* find the maximum points in dir1 starting at 1 */
318  num_max = 0; ind[0]=-1; ind[1]=-1; ind[2]=-1; max=-1.0;
319  for (i=0;i<num_vec;i++) {
320  if (vec[i][dir1] > max) {
321  max = vec[i][dir1]; ind[0] = i; num_max = 1;
322  } else if (fabs(vec[i][dir1] - max) < MSQ_MACHINE_EPS) {
323  ind[num_max++] = i;
324  }
325  }
326  if (max <= 0) *status = MSQ_NO_EQUIL;
327 
328  if (*status != MSQ_NO_EQUIL) {
329  switch(num_max) {
330  case 1: /* rotate to find the next point */
331  MSQ_COPY_VECTOR(pt1,vec[ind[0]],3);
332  pt_1 = pt1[dir1]; pt_2 = pt1[dir2];
333  if (pt1[dir2] < 0){rotate=MSQ_CW; min_inv_slope=1E300;}
334  if (pt1[dir2] >= 0){rotate=MSQ_CCW; max_inv_slope=-1E300;}
335  switch(rotate) {
336  case MSQ_CCW:
337  for (i=0;i<num_vec;i++) {
338  if (i!=ind[0]) {
339  inv_slope = (vec[i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
340  if (inv_slope>max_inv_slope) {
341  ind[1] = i; max_inv_slope=inv_slope; num_rotated = 1;
342  } else if (fabs(inv_slope - max_inv_slope) < MSQ_MACHINE_EPS) {
343  ind[2] = i; num_rotated++;
344  }
345  }
346  }
347  break;
348  case MSQ_CW:
349  for (i=0;i<num_vec;i++) {
350  if (i!=ind[0]) {
351  inv_slope = (vec[i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
352  if (inv_slope<min_inv_slope) {
353  ind[1] = i; min_inv_slope=inv_slope; num_rotated = 1;
354  } else if (fabs(inv_slope - min_inv_slope) < MSQ_MACHINE_EPS) {
355  ind[2] = i; num_rotated++;
356  }
357  }
358  }
359  }
360  switch(num_rotated) {
361  case 0:
362  MSQ_PRINT(3)("No points in the rotation ... odd\n");
363  *status = MSQ_HULL_TEST_ERROR;
364  break;
365  case 1:
366  MSQ_PRINT(3)("Found a line in the convex hull\n");
367  MSQ_COPY_VECTOR(pt2,vec[ind[1]],3);
368  *status = MSQ_TWO_PT_PLANE;
369  break;
370  default:
371  MSQ_PRINT(3)("Found 2 or more points in the rotation\n");
372  /* check to see if rotation got past origin */
373  inv_origin_slope = pt_2/pt_1;
374  switch(rotate) {
375  case MSQ_CCW:
376  if (inv_origin_slope >= max_inv_slope) *status=MSQ_NO_EQUIL;
377  else if (dir1 == 2) *status=MSQ_CHECK_Y_COORD_DIRECTION;
378  else if (dir1 == 1) *status=MSQ_CHECK_X_COORD_DIRECTION;
379  else *status=MSQ_EQUIL;
380  break;
381  case MSQ_CW:
382  if (inv_origin_slope <= min_inv_slope) *status=MSQ_NO_EQUIL;
383  else if (dir1 == 2) *status=MSQ_CHECK_Y_COORD_DIRECTION;
384  else if (dir1 == 1) *status=MSQ_CHECK_X_COORD_DIRECTION;
385  else *status=MSQ_EQUIL;
386  }
387  }
388  break;
389  case 2: /* use these two points to define the plane */
390  MSQ_COPY_VECTOR(pt1,vec[ind[0]],3);
391  MSQ_COPY_VECTOR(pt2,vec[ind[1]],3);
392  *status = MSQ_TWO_PT_PLANE;
393  break;
394  default: /* check to see if all > 0 */
395  MSQ_PRINT(3)("Found 3 in max plane %f\n",max);
396  if (vec[ind[0]][dir1] <= 0) *status = MSQ_NO_EQUIL;
397  else if (dir1==2) *status=MSQ_CHECK_Y_COORD_DIRECTION;
398  else if (dir1==1) *status=MSQ_CHECK_X_COORD_DIRECTION;
399  else *status = MSQ_EQUIL;
400  }
401  }
402  }
403 
404 }
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
blockLoc i
Definition: read.cpp:79
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.

Here is the call graph for this function:

Here is the caller graph for this function:

void find_plane_points ( int  dir1,
int  dir2,
double **  vec,
int  num_vec,
double *  pt1,
double *  pt2,
double *  pt3,
int *  opt_status,
MsqError err 
)
private
void form_grammian ( double **  vec,
MsqError err 
)
inlineprivate

Definition at line 639 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, MsqError::INVALID_STATE, j, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mG, MSQ_DOT, MSQ_SETERR, and ActiveSet::num_active.

Referenced by NonSmoothSteepestDescent::check_equilibrium(), and NonSmoothSteepestDescent::search_direction().

640 {
641  int i, j;
642  int num_active = mActive->num_active;
643 
644  if (num_active > 150) {
645  MSQ_SETERR(err)("Exceeded maximum allowed active values",MsqError::INVALID_STATE);
646  return;
647  }
648  /* form the grammian with the dot products of the gradients */
649  for (i=0; i<num_active; i++) {
650  for (j=i; j<num_active; j++) {
651  mG[i][j] = 0.;
652  MSQ_DOT(mG[i][j],vec[i],vec[j],mDimension);
653  mG[j][i] = mG[i][j];
654  }
655  }
656 }
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
object is in an invalid state

Here is the caller graph for this function:

void form_grammian ( double **  vec,
MsqError err 
)
private
void form_PD_grammian ( MsqError err)
private
void form_PD_grammian ( MsqError err)
inlineprivate

Definition at line 830 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, i, MsqError::INVALID_STATE, j, k, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mPDG, MSQ_SETERR, ActiveSet::num_active, NonSmoothSteepestDescent::pdgInd, and NonSmoothSteepestDescent::singular_test().

Referenced by NonSmoothSteepestDescent::search_direction().

831 {
832  int i,j,k;
833  int g_ind_1;
834  int singular;
835 
836  int num_active = mActive->num_active;
837 
838  /* this assumes the grammian has been formed */
839  for (i=0;i<num_active;i++) {
840  for (j=0;j<num_active;j++) {
841  if (mG[i][j]==-1) {
842  MSQ_SETERR(err)("Grammian not computed properly",MsqError::INVALID_STATE);
843  return;
844  }
845  }
846  }
847 
848  /* use the first gradient in the active set */
849  g_ind_1 = 0;
850  mPDG[0][0] = mG[0][0];
851  pdgInd[0] = mActive->active_ind[0];
852 
853  /* test the rest and add them as appropriate */
854  k = 1; i = 1;
855  while( (k<mDimension) && (i < num_active) ) {
856  mPDG[0][k] = mPDG[k][0] = mG[0][i];
857  mPDG[k][k] = mG[i][i];
858  if ( k == 2) { /* add the dot product of g1 and g2 */
859  mPDG[1][k] = mPDG[k][1] = mG[g_ind_1][i];
860  }
861  this->singular_test(k+1,mPDG,&singular,err);
862  if (!singular) {
863  pdgInd[k] = mActive->active_ind[i];
864  if (k==1) g_ind_1 = i;
865  k++;
866  }
867  i++;
868  }
869 }
j indices k indices k
Definition: Indexing.h:6
void singular_test(int n, double **A, int *singular, MsqError &err)
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
object is in an invalid state

Here is the call graph for this function:

Here is the caller graph for this function:

void form_reduced_matrix ( double ***  P,
MsqError err 
)
inlineprivate

Definition at line 973 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, j, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mG, and ActiveSet::num_active.

Referenced by NonSmoothSteepestDescent::search_direction().

975 {
976  int i,j;
977  int num_active = mActive->num_active;
978 
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));
982 
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];
988  }
989  }
990 }
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6

Here is the caller graph for this function:

void form_reduced_matrix ( double ***  P,
MsqError err 
)
private
void get_active_directions ( double **  gradient,
double ***  dir,
MsqError err 
)
private
void get_active_directions ( double **  gradient,
double ***  dir,
MsqError err 
)
inlineprivate

Definition at line 502 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, i, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, MSQ_COPY_VECTOR, and ActiveSet::num_active.

Referenced by NonSmoothSteepestDescent::check_equilibrium(), and NonSmoothSteepestDescent::search_direction().

505 {
506  int i;
507  int num_active = mActive->num_active;
508 
509  (*dir) =(double **)malloc(sizeof(double *)*num_active);
510  for (i=0;i<num_active;i++) {
511  (*dir)[i] =(double *)malloc(sizeof(double)*mDimension);
512  MSQ_COPY_VECTOR((*dir)[i],gradient[mActive->active_ind[i]],mDimension);
513  }
514 }
blockLoc i
Definition: read.cpp:79

Here is the caller graph for this function:

void get_gradient_projections ( MsqError err)
inlineprivate

Definition at line 1016 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mGradient, NonSmoothSteepestDescent::mGS, NonSmoothSteepestDescent::mSearch, MSQ_DOT, MSQ_PRINT, NonSmoothSteepestDescent::mSteepest, and NonSmoothSteepestDescent::numFunctionValues.

Referenced by NonSmoothSteepestDescent::minmax_opt().

Here is the caller graph for this function:

void get_gradient_projections ( MsqError err)
private
void get_min_estimate ( double *  final_est,
MsqError err 
)
inlineprivate

Definition at line 993 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, i, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mAlpha, NonSmoothSteepestDescent::mGS, MSQ_MACHINE_EPS, ActiveSet::num_active, and NonSmoothSteepestDescent::numFunctionValues.

Referenced by NonSmoothSteepestDescent::step_acceptance().

995 {
996  int i;
997  double est_imp;
998 
999  *final_est = -1E300;
1000  for (i=0;i<mActive->num_active;i++) {
1001  est_imp = -mAlpha*mGS[mActive->active_ind[i]];
1002  if (est_imp>*final_est) *final_est = est_imp;
1003  }
1004  if (*final_est == 0) {
1005  *final_est = -1E300;
1006  for (i=0;i<numFunctionValues;i++) {
1007  est_imp = -mAlpha*mGS[i];
1008  if ((est_imp>*final_est) && (fabs(est_imp) > MSQ_MACHINE_EPS)) {
1009  *final_est = est_imp;
1010  }
1011  }
1012  }
1013 }
blockLoc i
Definition: read.cpp:79

Here is the caller graph for this function:

void get_min_estimate ( double *  final_est,
MsqError err 
)
private
int improvement_check ( MsqError err)
private

Definition at line 195 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References NonSmoothSteepestDescent::mActive, MSQ_PRINT, NonSmoothSteepestDescent::originalValue, and ActiveSet::true_active_value.

Referenced by NonSmoothSteepestDescent::step_acceptance().

196 {
197  int improved = 1;
198 
199  /* check to see that the mesh didn't get worse */
200  if (originalValue < mActive->true_active_value) {
201  MSQ_PRINT(2)("The local mesh got worse; initial value %f; final value %f\n",
203  improved = 0;
204  }
205 
206  return(improved);
207 
208 }
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.

Here is the caller graph for this function:

int improvement_check ( MsqError err)
private
void init_max_step_length ( MsqError err)
private
void init_max_step_length ( MsqError err)
inlineprivate

Definition at line 1172 of file includeLinks/NonSmoothSteepestDescent.hpp.

References i, MsqError::INVALID_MESH, j, k, NonSmoothSteepestDescent::maxAlpha, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mDimension, MSQ_PRINT, MSQ_SETERR, NonSmoothSteepestDescent::numElements, NonSmoothSteepestDescent::numVertices, and sqrt().

Referenced by NonSmoothSteepestDescent::optimize_vertex_positions().

1173 {
1174  int i, j, k;
1175  double max_diff = 0;
1176  double diff=0;
1177 
1178  MSQ_PRINT(2)("In init_max_step_length\n");
1179 
1180  /* check that the input data is correct */
1181  if (numElements==0) {
1182  MSQ_SETERR(err)("Num incident vtx = 0\n",MsqError::INVALID_MESH);
1183  return;
1184  }
1185  if ((mDimension!=2) && (mDimension!=3)) {
1186  MSQ_SETERR(err)("Problem dimension is incorrect", MsqError::INVALID_MESH);
1187  return;
1188  }
1189 
1190  /* find the maximum distance between two incident vertex locations */
1191  for (i=1;i<numVertices;i++) {
1192  for (j=i;j<numVertices+1;j++) {
1193  diff=0;
1194  for (k=0;k<mDimension;k++) {
1195  diff += (mCoords[i][k]-mCoords[j][k])*(mCoords[i][k]-mCoords[j][k]);
1196  }
1197  if (max_diff < diff) max_diff=diff;
1198  }
1199  }
1200  max_diff = sqrt(max_diff);
1201  if (max_diff==0) {
1202  MSQ_SETERR(err)("Maximum distance between incident vertices = 0\n",
1204  return;
1205  }
1206  maxAlpha = max_diff/100;
1207 
1208  MSQ_PRINT(3)(" Maximum step is %g\n",maxAlpha);
1209 }
j indices k indices k
Definition: Indexing.h:6
double sqrt(double d)
Definition: double.h:73
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.

Here is the call graph for this function:

Here is the caller graph for this function:

void init_opt ( MsqError err)
private
void init_opt ( MsqError err)
inlineprivate

Definition at line 1121 of file includeLinks/NonSmoothSteepestDescent.hpp.

References NonSmoothSteepestDescent::equilibriumPt, i, MsqError::INVALID_STATE, NonSmoothSteepestDescent::iterCount, j, NonSmoothSteepestDescent::mAlpha, NonSmoothSteepestDescent::maxAlpha, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mGradient, NonSmoothSteepestDescent::mGS, NonSmoothSteepestDescent::mPDG, NonSmoothSteepestDescent::mSearch, MSQ_PRINT, MSQ_SETERR, NonSmoothSteepestDescent::mSteepest, NonSmoothSteepestDescent::numFunctionValues, NonSmoothSteepestDescent::optIterCount, NonSmoothSteepestDescent::optStatus, NonSmoothSteepestDescent::originalFunction, NonSmoothSteepestDescent::pdgInd, NonSmoothSteepestDescent::prevActiveValues, and NonSmoothSteepestDescent::testFunction.

Referenced by NonSmoothSteepestDescent::optimize_vertex_positions().

1122 {
1123  int i, j;
1124 
1125  MSQ_PRINT(2)("\nInitializing Optimization \n");
1126  if (numFunctionValues > 150) {
1127  MSQ_SETERR(err)("num_values exceeds 150", MsqError::INVALID_STATE);
1128  }
1129  /* for the purposes of initialization will be set to zero after */
1130  equilibriumPt = 0;
1131  optStatus = 0;
1132  iterCount = 0;
1133  optIterCount = 0;
1134  mSteepest = 0;
1135  mAlpha = 0;
1136  maxAlpha = 0;
1137 
1138  MSQ_PRINT(3)(" Initialized Constants \n");
1139  for (i=0;i<3;i++) {
1140  mSearch[i] = 0;
1141  pdgInd[i] = -1;
1142  for (j=0;j<3;j++) mPDG[i][j] = 0;
1143  }
1144 
1145  MSQ_PRINT(3)(" Initialized search and PDG \n");
1146  for (i=0;i<numFunctionValues;i++) {
1147  mFunction[i] = 0;
1148  testFunction[i] = 0;
1149  originalFunction[i] = 0;
1150  mGS[i] = 0;
1151  for (j=0;j<3;j++) {
1152  mGradient[i][j] = 0;
1153  }
1154  }
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;
1159  }
1160  } else {
1161  for (i=0;i<numFunctionValues;i++) {
1162  for (j=0;j<numFunctionValues;j++) mG[i][j] = -1;
1163  }
1164  }
1165  MSQ_PRINT(3)(" Initialized G\n");
1166 
1167  for (i=0;i<100;i++) prevActiveValues[i] = 0;
1168  MSQ_PRINT(3)(" Initialized prevActiveValues\n");
1169 }
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
object is in an invalid state

Here is the caller graph for this function:

virtual void initialize ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

void initialize ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

Definition at line 73 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References NonSmoothSteepestDescent::activeEpsilon, PatchData::ELEMENTS_ON_VERTEX_PATCH, NonSmoothSteepestDescent::minAcceptableImprovement, NonSmoothSteepestDescent::minStepSize, MSQ_DBGOUT, and PatchDataUser::set_patch_type().

74 {
76 
77  // local parameter initialization
78  activeEpsilon = .00003;
79  // activeEpsilon = .000000003;
81  minStepSize = 1e-6;
82  MSQ_DBGOUT(1) << "- Executed NonSmoothSteepestDescent::initialize()\n";
83 }
virtual void set_patch_type(PatchData::PatchType patch_type, MsqError &err, int param1=0, int param2=0)
Sets the Patch Type.
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.

Here is the call graph for this function:

virtual void initialize_mesh_iteration ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

void initialize_mesh_iteration ( PatchData pd,
MsqError err 
)
protectedvirtual
void minmax_opt ( PatchData pd,
MsqError err 
)
private

Definition at line 548 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References NonSmoothSteepestDescent::check_equilibrium(), NonSmoothSteepestDescent::compute_alpha(), NonSmoothSteepestDescent::compute_gradient(), NonSmoothSteepestDescent::equilibriumPt, NonSmoothSteepestDescent::find_active_set(), NonSmoothSteepestDescent::freeVertexIndex, NonSmoothSteepestDescent::get_gradient_projections(), NonSmoothSteepestDescent::iterCount, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mGradient, MSQ_COPY_VECTOR, MSQ_DBG, MSQ_EQUILIBRIUM, MSQ_ERRRTN, MSQ_FLAT_NO_IMP, MSQ_FUNCTION_TIMER, MSQ_IMP_TOO_SMALL, MSQ_MAX_ITER_EXCEEDED, MSQ_MAX_OPT_ITER, MSQ_PRINT, MSQ_STEP_TOO_SMALL, MSQ_ZERO_SEARCH, ActiveSet::num_active, NonSmoothSteepestDescent::numFunctionValues, NonSmoothSteepestDescent::optIterCount, NonSmoothSteepestDescent::optStatus, NonSmoothSteepestDescent::originalFunction, NonSmoothSteepestDescent::originalValue, NonSmoothSteepestDescent::prevActiveValues, NonSmoothSteepestDescent::print_active_set(), NonSmoothSteepestDescent::search_direction(), NonSmoothSteepestDescent::step_acceptance(), ActiveSet::true_active_value, and NonSmoothSteepestDescent::validity_check().

Referenced by NonSmoothSteepestDescent::optimize_vertex_positions().

549 {
550 // int valid;
551  MSQ_FUNCTION_TIMER( "Minmax Opt" );
552  MSQ_PRINT(2)("In minmax_opt\n");
553 
556 
557  iterCount = 0;
558  optIterCount = 0;
559 
560  MSQ_PRINT(3)("Done copying original function to function\n");
561 
562  this->find_active_set(mFunction, mActive, err); MSQ_ERRRTN(err);
564 
565  /* check for equilibrium point */
566  /* compute the gradient */
567  mGradient = this->compute_gradient(&pd, err); MSQ_ERRRTN(err);
568 
569  if (mActive->num_active >= 2) {
570  MSQ_PRINT(3)("Testing for an equilibrium point \n");
572 
573  if (MSQ_DBG(2) && equilibriumPt )
574  MSQ_PRINT(2)("Optimization Exiting: An equilibrium point \n");
575  }
576 
577  /* terminate if we have found an equilibrium point or if the step is
578  too small to be worthwhile continuing */
579  while ((optStatus != MSQ_EQUILIBRIUM) &&
582  (optStatus != MSQ_FLAT_NO_IMP) &&
583  (optStatus != MSQ_ZERO_SEARCH) &&
585 
586  /* increase the iteration count by one */
587  /* smooth_param->iter_count += 1; */
588  iterCount += 1;
589  optIterCount += 1;
591 
592  MSQ_PRINT(3)("\nITERATION %d \n",iterCount);
593 
594  /* compute the gradient */
595  mGradient = this->compute_gradient(&pd, err); MSQ_ERRRTN(err);
596 
597  MSQ_PRINT(3)("Computing the search direction \n");
598  this->search_direction(pd, err); MSQ_ERRRTN(err);
599 
600  /* if there are viable directions to search */
601  if ((optStatus != MSQ_ZERO_SEARCH) &&
603 
604  MSQ_PRINT(3)("Computing the projections of the gradients \n");
605  this->get_gradient_projections(err); MSQ_ERRRTN(err);
606 
607  MSQ_PRINT(3)("Computing the initial step size \n");
608  this->compute_alpha(err); MSQ_ERRRTN(err);
609 
610  MSQ_PRINT(3)("Testing whether to accept this step \n");
611  this->step_acceptance(pd, err); MSQ_ERRRTN(err);
612  MSQ_PRINT(3)("The new free vertex position is %f %f %f\n",
614 
615  if (MSQ_DBG(3)) {
616  /* Print the active set */
617  this->print_active_set(mActive, mFunction, err);
618  MSQ_ERRRTN(err);
619  }
620 
621  /* check for equilibrium point */
622  if (mActive->num_active >= 2) {
623  MSQ_PRINT(3)("Testing for an equilibrium point \n");
624  this->check_equilibrium(&equilibriumPt, &optStatus, err);
625  MSQ_ERRRTN(err);
626 
627  if (MSQ_DBG(2) && equilibriumPt)
628  MSQ_PRINT(2)("Optimization Exiting: An equilibrium point \n");
629  }
630 
631  /* record the values */
633 
634  } else {
635  /* decrease the iteration count by one */
636  /* smooth_param->iter_count -= 1; */
637  iterCount -= 1;
638  if (MSQ_DBG(2)) {
639  MSQ_PRINT(2)("Optimization Exiting: No viable directions; equilibrium point \n");
640  /* Print the old active set */
641  this->print_active_set(mActive,mFunction,err); MSQ_ERRRTN(err);
642  }
643  }
644  }
645 
646  MSQ_PRINT(2)("Checking the validity of the mesh\n");
647  if (!this->validity_check(err)) MSQ_PRINT(2)("The final mesh is not valid\n");
648  MSQ_ERRRTN(err);
649 
650  MSQ_PRINT(2)("Number of optimization iterations %d\n", iterCount);
651 
652  switch(optStatus) {
653  case MSQ_EQUILIBRIUM:
654  MSQ_PRINT(2)("Optimization Termination OptStatus: Equilibrium\n"); break;
655  case MSQ_STEP_TOO_SMALL:
656  MSQ_PRINT(2)("Optimization Termination OptStatus: Step Too Small\n"); break;
657  case MSQ_IMP_TOO_SMALL:
658  MSQ_PRINT(2)("Optimization Termination OptStatus: Improvement Too Small\n"); break;
659  case MSQ_FLAT_NO_IMP:
660  MSQ_PRINT(2)("Optimization Termination OptStatus: Flat No Improvement\n"); break;
661  case MSQ_ZERO_SEARCH:
662  MSQ_PRINT(2)("Optimization Termination OptStatus: Zero Search\n"); break;
664  MSQ_PRINT(2)("Optimization Termination OptStatus: Max Iter Exceeded\n"); break;
665  }
666 }
#define MSQ_DBG(flag)
Check if a debug flag is activated - evaluates to a bool.
void check_equilibrium(int *equil, int *opt_status, MsqError &err)
double ** compute_gradient(PatchData *pd, MsqError &err)
void find_active_set(double *function, ActiveSet *active_set, MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
void print_active_set(ActiveSet *active_set, double *func, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

void minmax_opt ( PatchData pd,
MsqError err 
)
private
virtual void optimize_vertex_positions ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

void optimize_vertex_positions ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

Definition at line 89 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References NonSmoothSteepestDescent::compute_function(), NonSmoothSteepestDescent::find_active_set(), NonSmoothSteepestDescent::freeVertexIndex, PatchData::get_element_array(), QualityImprover::get_mesh_set(), PatchData::get_vertex_array(), MsqMeshEntity::get_vertex_indices(), NonSmoothSteepestDescent::init_max_step_length(), NonSmoothSteepestDescent::init_opt(), MsqError::INVALID_MESH, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mConnectivity, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::minmax_opt(), MSQ_DBG, MSQ_ERRRTN, MSQ_FUNCTION_TIMER, MSQ_PRINT, MSQ_SETERR, MsqFreeVertexIndexIterator::next(), PatchData::num_elements(), PatchData::num_free_vertices(), PatchData::num_vertices(), NonSmoothSteepestDescent::numElements, NonSmoothSteepestDescent::numFree, NonSmoothSteepestDescent::numFunctionValues, NonSmoothSteepestDescent::numVertices, NonSmoothSteepestDescent::originalFunction, MsqFreeVertexIndexIterator::reset(), MeshSet::space_dim(), NonSmoothSteepestDescent::validity_check(), and MsqFreeVertexIndexIterator::value().

91 {
92  MSQ_FUNCTION_TIMER( "NonSmoothSteepestDescent" );
93 
94  // cout << "- Executing NonSmoothSteepestDescent::optimize_node_positions()\n";
95  /* perform the min max smoothing algorithm */
96  MSQ_PRINT(2)("\nInitializing the patch iteration\n");
97 
99  MSQ_PRINT(3)("Number of Vertices: %d\n",numVertices);
100  numElements = pd.num_elements();
101  MSQ_PRINT(3)("Number of Elements: %d\n",numElements);
102  //Michael: Note: is this a reliable way to get the dimension?
104  MSQ_PRINT(3)("Spatial Dimension: %d\n",mDimension);
105 
106  numFree=pd.num_free_vertices(err); MSQ_ERRRTN(err);
107  MSQ_PRINT(3)("Num Free = %d\n",numFree);
108 
109  MsqFreeVertexIndexIterator free_iter(&pd, err); MSQ_ERRRTN(err);
110  free_iter.reset();
111  free_iter.next();
112  freeVertexIndex = free_iter.value();
113  MSQ_PRINT(3)("Free Vertex Index = %d\n",freeVertexIndex);
114 
115  mCoords = pd.get_vertex_array(err); MSQ_ERRRTN(err);
116 
117  if (MSQ_DBG(3)) {
118  for (int i99=0;i99<numVertices;i99++) {
119  MSQ_PRINT(3)("coords: %g %g\n",mCoords[i99][0],mCoords[i99][1]);
120  }
121  }
122 
124  if (MSQ_DBG(3)) {
125  msq_std::vector<size_t> indices;
126  for (int i99=0;i99<numElements;i99++) {
127  mConnectivity[i99].get_vertex_indices(indices);
128  MSQ_PRINT(3)("connectivity: %d %d %d\n",indices[0],
129  indices[1],indices[2]);
130  }
131  }
132 
133  // TODO - need to switch to validity via metric evaluations should
134  // be associated with the compute_function somehow
135  /* check for an invalid mesh; if it's invalid return and ask the user
136  to use untangle */
137  if (this->validity_check(err)!=1) {
138  MSQ_PRINT(1)("ERROR: Invalid mesh\n");
139  MSQ_SETERR(err)("Invalid Mesh: Use untangle to create a valid "
140  "triangulation", MsqError::INVALID_MESH);
141  return;
142  }
143 
144  /* assumes one function value per element */
145  // TODO - need to include vertex metrics
147 
148  /* initialize the optimization data up to numFunctionValues */
149  this->init_opt(err); MSQ_ERRRTN(err);
150  this->init_max_step_length(err); MSQ_ERRRTN(err);
151  MSQ_PRINT(3)("Done initializing optimization\n");
152 
153  /* compute the initial function values */
154  //TODO this should return a bool with the validity
155  this->compute_function(&pd, originalFunction, err); MSQ_ERRRTN(err);
156 
157  // find the initial active set
159 
160  this->minmax_opt(pd,err); MSQ_ERRRTN(err);
161 }
#define MSQ_DBG(flag)
Check if a debug flag is activated - evaluates to a bool.
int space_dim() const
Returns the number of coordinates in the Mesh&#39;s geometric coordinate system.
void get_vertex_indices(msq_std::vector< msq_stdc::size_t > &vertex_list) const
gets the vertices of the mesh entity
int num_free_vertices(MsqError &err) const
Returns the number of elements in the current patch who are free to move.
size_t num_elements() const
number of elements in the Patch.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
size_t num_vertices() const
number of vertices in the patch.
const MsqVertex * get_vertex_array(MsqError &err) const
Returns a pointer to the start of the vertex array.
void find_active_set(double *function, ActiveSet *active_set, MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
const MsqMeshEntity * get_element_array(MsqError &err) const
Returns a pointer to the start of the element array.
bool compute_function(PatchData *pd, double *function, MsqError &err)
iterates over indexes of free vetices in a PatchData.
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.

Here is the call graph for this function:

void print_active_set ( ActiveSet active_set,
double *  func,
MsqError err 
)
inlineprivate

Definition at line 1103 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, i, MsqError::INVALID_ARG, MSQ_DBGOUT, MSQ_PRINT, MSQ_SETERR, and ActiveSet::num_active.

Referenced by NonSmoothSteepestDescent::minmax_opt(), and NonSmoothSteepestDescent::search_direction().

1106 {
1107  if (active_set==0) {
1108  MSQ_SETERR(err)("Null ActiveSet", MsqError::INVALID_ARG);
1109  return;
1110  }
1111 
1112  if (active_set->num_active == 0) MSQ_DBGOUT(3)<< "No active values\n";
1113  /* print the active set */
1114  for (int i=0;i<active_set->num_active;i++) {
1115  MSQ_PRINT(3)("Active value %d: %f \n",
1116  i+1,func[active_set->active_ind[i]]);
1117  }
1118 }
invalid function argument passed
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.

Here is the caller graph for this function:

void print_active_set ( ActiveSet active_set,
double *  func,
MsqError err 
)
private
void search_direction ( PatchData pd,
MsqError err 
)
private
void search_direction ( PatchData pd,
MsqError err 
)
private

Definition at line 406 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References ActiveSet::active_ind, denom, NonSmoothSteepestDescent::form_grammian(), NonSmoothSteepestDescent::form_PD_grammian(), NonSmoothSteepestDescent::form_reduced_matrix(), NonSmoothSteepestDescent::get_active_directions(), i, MsqError::INVALID_STATE, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mGradient, NonSmoothSteepestDescent::mSearch, MSQ_CHKERR, MSQ_COPY_VECTOR, MSQ_DOT, MSQ_ERRRTN, MSQ_MACHINE_EPS, MSQ_NORMALIZE, MSQ_PRINT, MSQ_SETERR, MSQ_ZERO_SEARCH, NonSmoothSteepestDescent::mSteepest, ActiveSet::num_active, NonSmoothSteepestDescent::optStatus, NonSmoothSteepestDescent::print_active_set(), NonSmoothSteepestDescent::search_edges_faces(), NonSmoothSteepestDescent::singular_test(), NonSmoothSteepestDescent::solve2x2(), and x.

Referenced by NonSmoothSteepestDescent::minmax_opt().

408 {
409  int i;
410  int viable;
411  int singular;
412  double a, b, c, denom;
413  double **dir;
414  double R0, R1;
415  double **P, *x;
416  double search_mag;
417 
418  int num_active = mActive->num_active;
419 
420  //TODO This might be o.k. actually - i don't see any dependence
421  // on the element geometry here... try it and see if it works.
422  // if not, try taking all of the gradients in the active set
423  // and let the search direction be the average of those.
424 // MSQ_FUNCTION_TIMER( "Search Direction" );
425 
426  MSQ_PRINT(2)("\nIn Search Direction\n");
427  this->print_active_set(mActive, mFunction, err); MSQ_ERRRTN(err);
428 
429  if (num_active==0) {
430  MSQ_SETERR(err)("No active values in search",MsqError::INVALID_STATE);
431  return;
432  }
433 
434  switch(num_active) {
435  case 1:
438  break;
439  case 2:
440  /* if there are two active points, move in the direction of the
441  intersection of the planes. This is the steepest descent
442  direction found by analytically solving the QP */
443 
444  /* set up the active gradient directions */
445  this->get_active_directions(mGradient,&dir,err);
446  if (MSQ_CHKERR(err)) { free(dir); return; }
447 
448  /* form the grammian */
449  this->form_grammian(dir,err);
450  if (MSQ_CHKERR(err)) { free(dir); return; }
451  this->form_PD_grammian(err);
452  if (MSQ_CHKERR(err)) { free(dir); return; }
453 
454  denom = (mG[0][0] + mG[1][1] - 2*mG[0][1]);
455  viable = 1;
456  if (fabs(denom) > MSQ_MACHINE_EPS) {
457  /* gradients are LI, move along their intersection */
458  b = (mG[0][0] - mG[0][1])/denom;
459  a = 1 - b;
460  if ((b < 0) || (b > 1)) viable=0; /* 0 < b < 1 */
461  if (viable) {
462  for (i=0;i<mDimension;i++) {
463  mSearch[i] = a*dir[0][i] + b*dir[1][i];
464  }
465  } else {
466  /* the gradients are dependent, move along one face */
468  }
469  } else {
470  /* the gradients are dependent, move along one face */
472  }
474 
475  for (i=0;i<num_active;i++) free(dir[i]);
476  free(dir);
477 
478  break;
479  default:
480  /* as in case 2: solve the QP problem to find the steepest
481  descent direction. This can be done analytically - as
482  is done in Gill, Murray and Wright
483  for 3 active points in 3 directions - test PD of G
484  otherwise we know it's SP SD so search edges and faces */
485 
486  /* get the active gradient directions */
487  this->get_active_directions(mGradient,&dir,err); MSQ_ERRRTN(err);
488 
489  /* form the entries of the grammian matrix */
490  this->form_grammian(dir,err);
491  if (MSQ_CHKERR(err)) { free(dir); return; }
492  this->form_PD_grammian(err);
493  if (MSQ_CHKERR(err)) { free(dir); return; }
494 
495  switch(mDimension) {
496  case 2:
497  this->search_edges_faces(dir,err);
498  if (MSQ_CHKERR(err)) { free(dir); return; }
499  break;
500  case 3:
501  if (num_active == 3) {
502  this->singular_test(num_active,mG,&singular,err);
503  if (MSQ_CHKERR(err)) { free(dir); return; }
504  if (!singular) {
505  /* form the entries of P=Z^T G Z where Z = [-1...-1; I ] */
506  this->form_reduced_matrix(&P,err);
507  if (MSQ_CHKERR(err)) { free(dir); return; }
508  /* form the RHS and solve the system for the coeffs */
509  R0 = mG[0][0] - mG[1][0]; R1 = mG[0][0] - mG[2][0];
510  this->solve2x2(P[0][0],P[0][1],P[1][0],P[1][1],R0,R1,&x,err);
511  if (MSQ_CHKERR(err)) { free(dir); return; }
512  if (x!=NULL) {
513  a = 1 - x[0] - x[1]; b = x[0]; c = x[1];
514  for (i=0;i<mDimension;i++) {
515  mSearch[i] = a*dir[0][i] + b*dir[1][i] +
516  c*dir[2][i];
517  }
519  for (i=0;i<num_active-1;i++) free(P[i]);
520  free(P); free(x);
521  } else {
522  this->search_edges_faces(dir, err);
523  if (MSQ_CHKERR(err)) { free(dir); return; }
524  }
525  } else {
526  this->search_edges_faces(dir, err);
527  if (MSQ_CHKERR(err)) { free(dir); return; }
528  }
529  } else {
530  this->search_edges_faces(dir, err);
531  if (MSQ_CHKERR(err)) { free(dir); return; }
532  }
533  break;
534  }
535  for (i=0;i<num_active;i++) free(dir[i]);
536  free(dir);
537  }
538 
539  /* if the search direction is essentially zero, equilibrium pt */
540  MSQ_DOT(search_mag,mSearch,mSearch,mDimension);
541  MSQ_PRINT(3)(" Search Magnitude %g \n",search_mag);
542 
543  if (fabs(search_mag)<1E-13) optStatus = MSQ_ZERO_SEARCH;
544  else MSQ_NORMALIZE(mSearch,mDimension);
545  MSQ_PRINT(3)(" Search Direction %g %g Steepest %d\n",mSearch[0],mSearch[1],mSteepest);
546 }
void singular_test(int n, double **A, int *singular, MsqError &err)
void get_active_directions(double **gradient, double ***dir, MsqError &err)
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
void int int REAL * x
Definition: read.cpp:74
void solve2x2(double a11, double a12, double a21, double a22, double b1, double b2, double **x, MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
object is in an invalid state
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom
void print_active_set(ActiveSet *active_set, double *func, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

void search_edges_faces ( double **  dir,
MsqError err 
)
inlineprivate

Definition at line 872 of file includeLinks/NonSmoothSteepestDescent.hpp.

References ActiveSet::active_ind, denom, i, MsqError::INVALID_MESH, j, k, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mG, NonSmoothSteepestDescent::mSearch, MSQ_COPY_VECTOR, MSQ_DOT, MSQ_EQUILIBRIUM, MSQ_MACHINE_EPS, MSQ_SETERR, NonSmoothSteepestDescent::mSteepest, ActiveSet::num_active, NonSmoothSteepestDescent::optStatus, and projection().

Referenced by NonSmoothSteepestDescent::search_direction().

873 {
874 // int ierr;
875  int i,j,k;
876  int viable;
877  double a,b,denom;
878  double g_bar[3];
879  double temp_search[3];
880  double projection, min_projection;
881 
882  int num_active = mActive->num_active;
883 
884  if ( (mDimension != 2) && (mDimension != 3)) {
885  MSQ_SETERR(err)("Dimension must be 2 or 3", MsqError::INVALID_MESH);
886  }
887 
888  /* initialize the search direction to 0,0 */
889  for (i=0;i<mDimension;i++) temp_search[i] = 0;
890 
891  /* Check for viable faces */
892  min_projection = 1E300;
893  for (i=0; i<num_active; i++) {
894  /* FACE I */
895  viable = 1;
896 
897  /* test the viability */
898  for (j=0;j<num_active;j++) { /* lagrange multipliers>0 */
899  if (mG[j][i] < 0) viable = 0;
900  }
901 
902  /* find the minimum of viable directions */
903  if ((viable) && (mG[i][i] < min_projection)) {
904  min_projection = mG[i][i];
905  MSQ_COPY_VECTOR(temp_search,dir[i],mDimension);
907  }
908 
909  /* INTERSECTION IJ */
910  for (j=i+1; j<num_active; j++) {
911  viable = 1;
912 
913  /* find the coefficients of the intersection
914  and test the viability */
915  denom = 2*mG[i][j] - mG[i][i] - mG[j][j];
916  a = b = 0;
917  if (fabs(denom) > MSQ_MACHINE_EPS) {
918  b = (mG[i][j] - mG[i][i])/denom;
919  a = 1 - b;
920  if ((b < 0) || (b > 1)) viable=0; /* 0 < b < 1 */
921  for (k=0;k<num_active;k++) { /* lagrange multipliers>0 */
922  if ((a*mG[k][i] + b*mG[k][j]) <= 0) viable=0;
923  }
924  } else {
925  viable = 0; /* Linearly dependent */
926  }
927 
928  /* find the minimum of viable directions */
929  if (viable) {
930  for (k=0;k<mDimension;k++) {
931  g_bar[k] = a * dir[i][k] + b * dir[j][k];
932  }
933  MSQ_DOT(projection,g_bar,g_bar,mDimension);
934  if (projection < min_projection) {
935  min_projection = projection;
936  MSQ_COPY_VECTOR(temp_search,g_bar,mDimension);
938  }
939  }
940  }
941  }
942  if (optStatus != MSQ_EQUILIBRIUM) {
943  MSQ_COPY_VECTOR(mSearch,temp_search,mDimension);
944  }
945 }
j indices k indices k
Definition: Indexing.h:6
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
blockLoc i
Definition: read.cpp:79
j indices j
Definition: Indexing.h:6
CGAL_KERNEL_LARGE_INLINE PointS3< FT > projection(const PointS3< FT > &p, const PlaneS3< FT > &h)
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom

Here is the call graph for this function:

Here is the caller graph for this function:

void search_edges_faces ( double **  dir,
MsqError err 
)
private
void singular_test ( int  n,
double **  A,
int *  singular,
MsqError err 
)
private
void singular_test ( int  n,
double **  A,
int *  singular,
MsqError err 
)
inlineprivate

Definition at line 801 of file includeLinks/NonSmoothSteepestDescent.hpp.

References NonSmoothSteepestDescent::condition3x3(), MsqError::INVALID_ARG, MSQ_FALSE, MSQ_MACHINE_EPS, MSQ_SETERR, and MSQ_TRUE.

Referenced by NonSmoothSteepestDescent::form_PD_grammian(), and NonSmoothSteepestDescent::search_direction().

802 {
803 // int test;
804 // double determinant;
805  double cond;
806 
807  if ((n>3) || (n<1)) {
808  MSQ_SETERR(err)("Singular test works only for n=1 to n=3",MsqError::INVALID_ARG);
809  return;
810  }
811 
812  (*singular)=MSQ_TRUE;
813  switch(n) {
814  case 1:
815  if (A[0][0] > 0) (*singular) = MSQ_FALSE;
816  break;
817  case 2:
818  if (fabs(A[0][0]*A[1][1] - A[0][1]*A[1][0]) > MSQ_MACHINE_EPS)
819  (*singular) = MSQ_FALSE;
820  break;
821  case 3:
822  /* calculate the condition number */
823  this->condition3x3(A, &cond, err);
824  if (cond < 1E14) (*singular)=MSQ_FALSE;
825  break;
826  }
827 }
invalid function argument passed
rational * A
Definition: vinci_lass.c:67
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
const NT & n
void condition3x3(double **A, double *cond, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

void solve2x2 ( double  a11,
double  a12,
double  a21,
double  a22,
double  b1,
double  b2,
double **  x,
MsqError err 
)
inlineprivate

Definition at line 948 of file includeLinks/NonSmoothSteepestDescent.hpp.

References MSQ_MACHINE_EPS.

Referenced by NonSmoothSteepestDescent::search_direction().

952 {
953  double factor;
954 
955  /* if the system is not singular, solve it */
956  if (fabs(a11*a22 - a21*a12) > MSQ_MACHINE_EPS) {
957  (*x)=(double *)malloc(sizeof(double)*2);
958  if (fabs(a11) > MSQ_MACHINE_EPS) {
959  factor = (a21/a11);
960  (*x)[1] = (b2 - factor*b1)/(a22 - factor*a12);
961  (*x)[0] = (b1 - a12*(*x)[1])/a11;
962  } else if (fabs(a21) > MSQ_MACHINE_EPS) {
963  factor = (a11/a21);
964  (*x)[1] = (b1 - factor*b2)/(a12 - factor*a22);
965  (*x)[0] = (b2 - a22*(*x)[1])/a21;
966  }
967  } else {
968  (*x) = NULL;
969  }
970 }

Here is the caller graph for this function:

void solve2x2 ( double  a11,
double  a12,
double  a21,
double  a22,
double  b1,
double  b2,
double **  x,
MsqError err 
)
private
void step_acceptance ( PatchData pd,
MsqError err 
)
private
void step_acceptance ( PatchData pd,
MsqError err 
)
private

Definition at line 669 of file QualityImprover/VertexMover/NonSmoothSteepestDescent/NonSmoothSteepestDescent.cpp.

References NonSmoothSteepestDescent::compute_function(), NonSmoothSteepestDescent::copy_active(), NonSmoothSteepestDescent::find_active_set(), NonSmoothSteepestDescent::freeVertexIndex, NonSmoothSteepestDescent::get_min_estimate(), i, NonSmoothSteepestDescent::improvement_check(), NonSmoothSteepestDescent::iterCount, NonSmoothSteepestDescent::mActive, NonSmoothSteepestDescent::mAlpha, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mDimension, NonSmoothSteepestDescent::mFunction, NonSmoothSteepestDescent::minAcceptableImprovement, NonSmoothSteepestDescent::minStepSize, NonSmoothSteepestDescent::mSearch, MSQ_CHKERR, MSQ_COPY_VECTOR, MSQ_ERRRTN, MSQ_FALSE, MSQ_FLAT_NO_IMP, MSQ_IMP_TOO_SMALL, MSQ_PRINT, MSQ_STEP_ACCEPTED, MSQ_STEP_DONE, MSQ_STEP_NOT_DONE, MSQ_STEP_TOO_SMALL, MSQ_TRUE, NonSmoothSteepestDescent::numFunctionValues, NonSmoothSteepestDescent::optStatus, NonSmoothSteepestDescent::originalActive, NonSmoothSteepestDescent::originalFunction, NonSmoothSteepestDescent::prevActiveValues, NonSmoothSteepestDescent::testActive, NonSmoothSteepestDescent::testFunction, ActiveSet::true_active_value, and NonSmoothSteepestDescent::validity_check().

Referenced by NonSmoothSteepestDescent::minmax_opt().

670 {
671 // int ierr;
672  int i;
673  int num_values, num_steps;
674  int valid = 1, step_status;
675  int accept_alpha;
676  double estimated_improvement;
677  double current_improvement = 1E300;
678  double previous_improvement = 1E300;
679  double current_percent_diff = 1E300;
680  double original_point[3];
681 
682 // MSQ_FUNCTION_TIMER( "Step Acceptance" );
683  num_values = numFunctionValues;
684 
685  step_status = MSQ_STEP_NOT_DONE;
686  optStatus = 0;
687  num_steps = 0;
688 
689  if (mAlpha < minStepSize) {
691  step_status = MSQ_STEP_DONE;
692  MSQ_PRINT(3)("Alpha starts too small, no improvement\n");
693  }
694 
695  /* save the original function and active set */
698  this->copy_active(mActive, originalActive, err); MSQ_ERRRTN(err);
699 
700  while (step_status == MSQ_STEP_NOT_DONE) {
701 
702  num_steps++; if (num_steps >= 100) step_status = MSQ_STEP_DONE;
703 
704  accept_alpha = MSQ_FALSE;
705 
706  while (!accept_alpha && mAlpha>minStepSize) {
707 
708  /* make the step */
709  for (i=0;i<mDimension;i++) {
711  }
712  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
713 
714  MSQ_PRINT(2)("search direction %f %f \n",mSearch[0],mSearch[1]);
715  MSQ_PRINT(2)("new vertex position %f %f \n",mCoords[freeVertexIndex][0],mCoords[freeVertexIndex][1]);
716 
717  /* assume alpha is acceptable */
718  accept_alpha=MSQ_TRUE;
719 
720  /* never take a step that makes a valid mesh invalid or worsens the quality */
721  // TODO Validity check revision -- do the compute function up here
722  // and then the rest based on validity
723  valid = validity_check(err); MSQ_ERRRTN(err);
724  if (valid) valid=improvement_check(err); MSQ_ERRRTN(err);
725  if (!valid) {
726  accept_alpha=MSQ_FALSE;
727  for (i=0;i<mDimension;i++) {
729  }
730  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
731  mAlpha = mAlpha/2;
732  MSQ_PRINT(2)("Step not accepted, the new alpha %f\n",mAlpha);
733 
734  if (mAlpha < minStepSize) {
736  step_status = MSQ_STEP_DONE;
737  MSQ_PRINT(2)("Step too small\n");
738  /* get back the original point, mFunction, and active set */
739  MSQ_COPY_VECTOR(mCoords[freeVertexIndex],original_point,mDimension);
740  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
742  this->copy_active(originalActive, mActive, err);
743  }
744  }
745  }
746 
747  if (valid && (mAlpha > minStepSize)) {
748  /* compute the new function and active set */
749  this->compute_function(&pd, mFunction, err); MSQ_ERRRTN(err);
750  this->find_active_set(mFunction, mActive, err); MSQ_ERRRTN(err);
751 
752  /* estimate the minimum improvement by taking this step */
753  this->get_min_estimate(&estimated_improvement, err); MSQ_ERRRTN(err);
754  MSQ_PRINT(2)("The estimated improvement for this step: %f\n",
755  estimated_improvement);
756 
757  /* calculate the actual increase */
758  current_improvement = mActive->true_active_value - prevActiveValues[iterCount-1];
759 
760  MSQ_PRINT(3)("Actual improvement %f\n",current_improvement);
761 
762  /* calculate the percent difference from estimated increase */
763  current_percent_diff = fabs(current_improvement-estimated_improvement)/
764  fabs(estimated_improvement);
765 
766  /* determine whether to accept a step */
767  if ((fabs(previous_improvement) > fabs(current_improvement)) &&
768  (previous_improvement < 0)) {
769  /* accept the previous step - it was better */
770  MSQ_PRINT(2)("Accepting the previous step\n");
771 
772  /* subtract alpha in again (previous step) */
773  for (i=0;i<mDimension;i++) {
775  }
776  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
777 
778  /* does this make an invalid mesh valid? */
779  //TODO Validity check revisison
780  valid = 1;
781  valid = validity_check(err); MSQ_ERRRTN(err);
782  if (valid) valid=improvement_check(err); MSQ_ERRRTN(err);
783 
784  /* copy test function and active set */
786  this->copy_active(testActive, mActive, err); MSQ_ERRRTN(err);
787 
788  optStatus = MSQ_STEP_ACCEPTED; step_status = MSQ_STEP_DONE;
789 
790  /* check to see that we're still making good improvements */
791  if (fabs(previous_improvement) < minAcceptableImprovement) {
792  optStatus = MSQ_IMP_TOO_SMALL; step_status = MSQ_STEP_DONE;
793  MSQ_PRINT(2)("Optimization Exiting: Improvement too small\n");
794  }
795 
796  } else if (((fabs(current_improvement) > fabs(estimated_improvement)) ||
797  (current_percent_diff < .1)) && (current_improvement<0)) {
798  /* accept this step, exceeded estimated increase or was close */
799  optStatus = MSQ_STEP_ACCEPTED; step_status = MSQ_STEP_DONE;
800 
801  /* check to see that we're still making good improvements */
802  if (fabs(current_improvement) < minAcceptableImprovement) {
803  MSQ_PRINT(2)("Optimization Exiting: Improvement too small\n");
804  optStatus = MSQ_IMP_TOO_SMALL; step_status = MSQ_STEP_DONE;
805  }
806 
807  } else if ((current_improvement > 0) && (previous_improvement > 0) &&
808  (fabs(current_improvement) < minAcceptableImprovement) &&
809  (fabs(previous_improvement) < minAcceptableImprovement)) {
810 
811  /* we are making no progress, quit */
812  optStatus = MSQ_FLAT_NO_IMP; step_status = MSQ_STEP_DONE;
813  MSQ_PRINT(2)("Opimization Exiting: Flat no improvement\n");
814 
815  /* get back the original point, function, and active set */
816  MSQ_COPY_VECTOR(mCoords[freeVertexIndex],original_point,mDimension);
817  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
819  this->copy_active(originalActive, mActive, err); MSQ_CHKERR(err);
820 
821  }
822  else
823  {
824  /* halve alpha and try again */
825  /* add out the old step */
826  for (i=0;i<mDimension;i++) mCoords[freeVertexIndex][i] += mAlpha*mSearch[i];
827  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
828 
829  /* halve step size */
830  mAlpha = mAlpha/2;
831  MSQ_PRINT(3)("Step not accepted, the new alpha %f\n",mAlpha);
832 
833  if (mAlpha < minStepSize)
834  {
835  /* get back the original point, function, and active set */
836  MSQ_PRINT(2)("Optimization Exiting: Step too small\n");
837  MSQ_COPY_VECTOR(mCoords[freeVertexIndex],original_point,mDimension);
838  //pd.set_coords_array_element(mCoords[freeVertexIndex],0,err);
840  this->copy_active(originalActive, mActive, err); MSQ_ERRRTN(err);
841  optStatus = MSQ_STEP_TOO_SMALL; step_status = MSQ_STEP_DONE;
842  }
843  else
844  {
846  this->copy_active(mActive, testActive, err); MSQ_ERRRTN(err);
847  previous_improvement = current_improvement;
848  }
849  }
850  }
851  }
852  if (current_improvement>0 && optStatus==MSQ_STEP_ACCEPTED) {
853  MSQ_PRINT(2)("Accepted a negative step %f \n",current_improvement);
854  }
855 
856 }
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
blockLoc i
Definition: read.cpp:79
void get_min_estimate(double *final_est, MsqError &err)
void find_active_set(double *function, ActiveSet *active_set, MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
bool compute_function(PatchData *pd, double *function, MsqError &err)
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
void copy_active(ActiveSet *active1, ActiveSet *active2, MsqError &err)

Here is the call graph for this function:

Here is the caller graph for this function:

void terminate_mesh_iteration ( PatchData pd,
MsqError err 
)
protectedvirtual
virtual void terminate_mesh_iteration ( PatchData pd,
MsqError err 
)
protectedvirtual

Implements VertexMover.

int validity_check ( MsqError err)
private
int validity_check ( MsqError err)
inlineprivate

Definition at line 394 of file includeLinks/NonSmoothSteepestDescent.hpp.

References Vector3D::get_coordinates(), MsqMeshEntity::get_vertex_index(), i, NonSmoothSteepestDescent::mConnectivity, NonSmoothSteepestDescent::mCoords, NonSmoothSteepestDescent::mDimension, MSQ_MACHINE_EPS, NonSmoothSteepestDescent::numElements, and sqrt().

Referenced by NonSmoothSteepestDescent::minmax_opt(), NonSmoothSteepestDescent::optimize_vertex_positions(), and NonSmoothSteepestDescent::step_acceptance().

396 {
397 // FUNCTION_TIMER_START("Validity Check");
398 
399  // ONLY FOR SIMPLICIAL MESHES - THERE SHOULD BE A VALIDITY CHECKER ASSOCIATED
400  // WITH MSQ ELEMENTS
401 
402  /* check that the simplicial mesh is still valid, based on right handedness.
403  Returns a 1 or a 0 */
404 
405  // TODO as a first step we can switch this over to the function
406  // evaluation and use the rest of the code as is
407  int valid = 1;
408  double dEps = 1.e-13;
409 
410  double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4;
411 
412  if (mDimension == 2)
413  {
414  for (int i=0;i<numElements;i++)
415  {
416  double dummy = 0;
420 
421  double a = x2*y3 - x3*y2;
422  double b = y2 - y3;
423  double c = x3 - x2;
424 
425  if (.5*(a+b*x1+c*y1) < .01*MSQ_MACHINE_EPS)
426  valid=0;
427  }
428  }
429 
430  if (mDimension == 3)
431  {
432  for (int i=0;i<numElements;i++)
433  {
438 
439  double dDX2 = x2 - x1;
440  double dDX3 = x3 - x1;
441  double dDX4 = x4 - x1;
442 
443  double dDY2 = y2 - y1;
444  double dDY3 = y3 - y1;
445  double dDY4 = y4 - y1;
446 
447  double dDZ2 = z2 - z1;
448  double dDZ3 = z3 - z1;
449  double dDZ4 = z4 - z1;
450 
451  /* dDet is proportional to the cell volume */
452  double dDet = dDX2*dDY3*dDZ4 + dDX3*dDY4*dDZ2 + dDX4*dDY2*dDZ3
453  - dDZ2*dDY3*dDX4 - dDZ3*dDY4*dDX2 - dDZ4*dDY2*dDX3 ;
454 
455  /* Compute a length scale based on edge lengths. */
456  double dScale = ( sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) +
457  (z1-z2)*(z1-z2)) +
458  sqrt((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3) +
459  (z1-z3)*(z1-z3)) +
460  sqrt((x1-x4)*(x1-x4) + (y1-y4)*(y1-y4) +
461  (z1-z4)*(z1-z4)) +
462  sqrt((x2-x3)*(x2-x3) + (y2-y3)*(y2-y3) +
463  (z2-z3)*(z2-z3)) +
464  sqrt((x2-x4)*(x2-x4) + (y2-y4)*(y2-y4) +
465  (z2-z4)*(z2-z4)) +
466  sqrt((x3-x4)*(x3-x4) + (y3-y4)*(y3-y4) +
467  (z3-z4)*(z3-z4)) ) / 6.;
468 
469  /* Use the length scale to get a better idea if the tet is flat or
470  just really small. */
471  if (fabs(dScale) < MSQ_MACHINE_EPS)
472  {
473  return(valid = 0);
474  }
475  else
476  {
477  dDet /= (dScale*dScale*dScale);
478  }
479 
480  if (dDet > dEps)
481  {
482  valid = 1;
483  }
484  else if (dDet < -dEps)
485  {
486  valid = -1;
487  }
488  else
489  {
490  valid = 0;
491  }
492  } // end for i=1,numElements
493  } // end mDimension==3
494 
495  // MSQ_DEBUG_ACTION(2,{fprintf(stdout,"Mesh Validity is: %d \n",valid);});
496 
497 // FUNCTION_TIMER_END();
498  return(valid);
499 }
msq_stdc::size_t get_vertex_index(msq_stdc::size_t vertex_in_element) const
double sqrt(double d)
Definition: double.h:73
void get_coordinates(double &x, double &y, double &z) const
blockLoc i
Definition: read.cpp:79

Here is the call graph for this function:

Here is the caller graph for this function:

Member Data Documentation

int equilibriumPt
private
double minAcceptableImprovement
private
int numFree
private

The documentation for this class was generated from the following files: