40 #include "MeshSet.hpp" 
   41 #include "MsqTimer.hpp" 
   43 using namespace Mesquite;
 
   48   this->
set_name(
"NonSmoothSteepestDescent");
 
   50   mFunction = (
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);
 
   61     mGradient[
i] = (
double *)malloc(
sizeof(
double)*3);
 
   62     mG[
i] = (
double *)malloc(
sizeof(
double)*150);
 
   64   for (i=0;i<3;i++) 
mPDG[i] = (
double *)malloc(
sizeof(
double)*3);
 
   69   MSQ_DBGOUT(1) << 
"- Executed NonSmoothSteepestDescent::NonSmoothSteepestDescent()\n";
 
   82   MSQ_DBGOUT(1) << 
"- Executed NonSmoothSteepestDescent::initialize()\n";
 
   96   MSQ_PRINT(2)(
"\nInitializing the patch iteration\n");
 
  125     msq_std::vector<size_t> indices;
 
  128       MSQ_PRINT(3)(
"connectivity: %d %d %d\n",indices[0],
 
  129               indices[1],indices[2]);
 
  139       MSQ_SETERR(err)(
"Invalid Mesh: Use untangle to create a valid " 
  151   MSQ_PRINT(3)(
"Done initializing optimization\n");
 
  171   MSQ_DBGOUT(1) << 
"- Executing NonSmoothSteepestDescent::cleanup()\n";
 
  173   for (i=0;i<150;i++) {
 
  177   for (i=0;i<3;i++) free(
mPDG[i]);
 
  190   MSQ_DBGOUT(1) << 
"- Done with NonSmoothSteepestDescent::cleanup()\n";
 
  200   if (originalValue < mActive->true_active_value) {
 
  201      MSQ_PRINT(2)(
"The local mesh got worse; initial value %f; final value %f\n",
 
  214                                                  double **vec, 
int num_vec,
 
  215                                                  double *pt1, 
double *pt2,
 
  216                                                  double* , 
int *status,
 
  220     int ind[50], num_min, num_max;
 
  224     double min, inv_slope;
 
  225     double min_inv_slope=0.;
 
  227     double max_inv_slope=0;
 
  228     double inv_origin_slope=0;
 
  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;
 
  246         pt_1 = pt1[dir1]; pt_2 = pt1[dir2];
 
  251           for (i=0;i<num_vec;i++) {
 
  253               inv_slope = (vec[
i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
 
  254               if ((inv_slope>max_inv_slope) &&  
 
  256                 ind[1] = 
i; max_inv_slope=inv_slope; num_rotated = 1;
 
  258                 ind[2] = 
i; num_rotated++;
 
  264           for (i=0;i<num_vec;i++) {
 
  266               inv_slope = (vec[
i][dir2] - pt_2)/(vec[i][dir1]-pt_1);
 
  267               if ((inv_slope<min_inv_slope) && 
 
  269                 ind[1] = 
i; min_inv_slope=inv_slope; num_rotated = 1;
 
  271                 ind[2] = 
i; num_rotated++;
 
  276         switch(num_rotated) {
 
  278           MSQ_PRINT(3)(
"No points in the rotation ... odd\n");
 
  282           MSQ_PRINT(3)(
"Found a line in the convex hull\n");
 
  286           MSQ_PRINT(3)(
"Found 2 or more points in the rotation\n");
 
  290             if (inv_origin_slope >= max_inv_slope) *status=
MSQ_NO_EQUIL;
 
  294             if (inv_origin_slope <= min_inv_slope) *status=
MSQ_NO_EQUIL;
 
  300         MSQ_PRINT(3)(
"Found two minimum points to define the plane\n");
 
  306         MSQ_PRINT(3)(
"Found 3 or more points in min plane %f\n",
min);
 
  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;
 
  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;}
 
  337           for (i=0;i<num_vec;i++) {
 
  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;
 
  343                 ind[2] = 
i; num_rotated++;
 
  349           for (i=0;i<num_vec;i++) {
 
  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;
 
  355                 ind[2] = 
i; num_rotated++;
 
  360         switch(num_rotated) {
 
  362           MSQ_PRINT(3)(
"No points in the rotation ... odd\n");
 
  366           MSQ_PRINT(3)(
"Found a line in the convex hull\n");
 
  371           MSQ_PRINT(3)(
"Found 2 or more points in the rotation\n");
 
  373           inv_origin_slope = pt_2/pt_1;
 
  376             if (inv_origin_slope >= max_inv_slope) *status=
MSQ_NO_EQUIL;
 
  382             if (inv_origin_slope <= min_inv_slope) *status=
MSQ_NO_EQUIL;
 
  412    double     a, b, c, 
denom;
 
  454         denom = (
mG[0][0] + 
mG[1][1] - 2*
mG[0][1]);
 
  458            b = (
mG[0][0] - 
mG[0][1])/denom;  
 
  460            if ((b < 0) || (b > 1)) viable=0;  
 
  475         for (i=0;i<num_active;i++) free(dir[i]);
 
  501           if (num_active == 3) {
 
  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);
 
  513                         a = 1 - x[0] - x[1];  b = x[0];  c = x[1];
 
  519                         for (i=0;i<num_active-1;i++)  free(P[i]);  
 
  535         for (i=0;i<num_active;i++) free(dir[i]);
 
  541     MSQ_PRINT(3)(
"  Search Magnitude %g \n",search_mag);
 
  560       MSQ_PRINT(3)(
"Done copying original function to function\n");
 
  570         MSQ_PRINT(3)(
"Testing for an equilibrium point \n");
 
  574           MSQ_PRINT(2)(
"Optimization Exiting: An equilibrium point \n");
 
  597         MSQ_PRINT(3)(
"Computing the search direction \n");
 
  604             MSQ_PRINT(3)(
"Computing the projections of the gradients \n");
 
  607             MSQ_PRINT(3)(
"Computing the initial step size \n");
 
  610             MSQ_PRINT(3)(
"Testing whether to accept this step \n");
 
  612             MSQ_PRINT(3)(
"The new free vertex position is %f %f %f\n",
 
  623                 MSQ_PRINT(3)(
"Testing for an equilibrium point \n");
 
  628                     MSQ_PRINT(2)(
"Optimization Exiting: An equilibrium point \n");
 
  639                 MSQ_PRINT(2)(
"Optimization Exiting: No viable directions; equilibrium point \n");
 
  646       MSQ_PRINT(2)(
"Checking the validity of the mesh\n");
 
  654           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Equilibrium\n"); 
break;
 
  656           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Step Too Small\n"); 
break;
 
  658           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Improvement Too Small\n"); 
break;
 
  660           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Flat No Improvement\n"); 
break;
 
  662           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Zero Search\n"); 
break;
 
  664           MSQ_PRINT(2)(
"Optimization Termination OptStatus: Max Iter Exceeded\n"); 
break;
 
  673   int        num_values, num_steps;
 
  674   int        valid = 1, step_status;
 
  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];
 
  692       MSQ_PRINT(3)(
"Alpha starts too small, no improvement\n");
 
  702     num_steps++;  
if (num_steps >= 100) step_status = 
MSQ_STEP_DONE;
 
  754       MSQ_PRINT(2)(
"The estimated improvement for this step: %f\n",
 
  755                    estimated_improvement); 
 
  760       MSQ_PRINT(3)(
"Actual improvement %f\n",current_improvement);
 
  763       current_percent_diff = fabs(current_improvement-estimated_improvement)/
 
  764         fabs(estimated_improvement);
 
  767       if ((fabs(previous_improvement) > fabs(current_improvement)) && 
 
  768           (previous_improvement < 0)) {
 
  770              MSQ_PRINT(2)(
"Accepting the previous step\n");
 
  793           MSQ_PRINT(2)(
"Optimization Exiting: Improvement too small\n");
 
  796       } 
else if (((fabs(current_improvement) > fabs(estimated_improvement)) ||
 
  797                   (current_percent_diff < .1)) && (current_improvement<0)) {
 
  803           MSQ_PRINT(2)(
"Optimization Exiting: Improvement too small\n");
 
  807       } 
else if ((current_improvement > 0) && (previous_improvement > 0) &&
 
  813         MSQ_PRINT(2)(
"Opimization Exiting: Flat no improvement\n");
 
  836           MSQ_PRINT(2)(
"Optimization Exiting: Step too small\n");
 
  847           previous_improvement = current_improvement;
 
  853     MSQ_PRINT(2)(
"Accepted a negative step %f \n",current_improvement);
 
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_CHECK_X_COORD_DIRECTION
#define MSQ_CHECK_BOTTOM_UP
double * originalFunction
#define MSQ_DBG(flag)
Check if a debug flag is activated - evaluates to a bool. 
void step_acceptance(PatchData &pd, MsqError &err)
size_t value()
Returns an index corresponding to a free vertex. 
#define MSQ_HULL_TEST_ERROR
int space_dim() const 
Returns the number of coordinates in the Mesh's geometric coordinate system. 
const MeshSet * get_mesh_set() const 
virtual void set_patch_type(PatchData::PatchType patch_type, MsqError &err, int param1=0, int param2=0)
Sets the Patch Type. 
#define MSQ_CHECK_TOP_DOWN
#define MSQ_STEP_ACCEPTED
void form_grammian(double **vec, MsqError &err)
Used to hold the error state and return it to the application. 
void check_equilibrium(int *equil, int *opt_status, MsqError &err)
void search_direction(PatchData &pd, MsqError &err)
void form_PD_grammian(MsqError &err)
#define MSQ_STEP_TOO_SMALL
virtual void terminate_mesh_iteration(PatchData &pd, MsqError &err)
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
double * prevActiveValues
double ** compute_gradient(PatchData *pd, MsqError &err)
void set_name(msq_std::string name)
provides a name to the QualityImprover (use it in constructor). 
double minAcceptableImprovement
void get_vertex_indices(msq_std::vector< msq_stdc::size_t > &vertex_list) const 
gets the vertices of the mesh entity 
virtual void initialize(PatchData &pd, MsqError &err)
void reset()
Resets the iterator. 
int num_free_vertices(MsqError &err) const 
Returns the number of elements in the current patch who are free to move. 
void singular_test(int n, double **A, int *singular, MsqError &err)
bool next()
Increments the iterator. returns false if there is no more free vertex. 
void minmax_opt(PatchData &pd, MsqError &err)
#define MSQ_MAX_ITER_EXCEEDED
int validity_check(MsqError &err)
size_t num_elements() const 
number of elements in the Patch. 
void get_active_directions(double **gradient, double ***dir, MsqError &err)
#define MSQ_CHKERR(err)
Mesquite's Error Checking macro. 
#define MSQ_NORMALIZE(v, n)
void init_opt(MsqError &err)
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear. 
#define MSQ_STEP_NOT_DONE
void search_edges_faces(double **dir, MsqError &err)
ObjectiveFunction * objFunc
#define MSQ_DOT(c, a, b, n)
MsqMeshEntity * mConnectivity
void get_min_estimate(double *final_est, MsqError &err)
void solve2x2(double a11, double a12, double a21, double a22, double b1, double b2, double **x, MsqError &err)
ActiveSet * originalActive
size_t num_vertices() const 
number of vertices in the patch. 
void form_reduced_matrix(double ***P, MsqError &err)
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
const MsqVertex * get_vertex_array(MsqError &err) const 
Returns a pointer to the start of the vertex array. 
virtual void initialize_mesh_iteration(PatchData &pd, MsqError &err)
void find_active_set(double *function, ActiveSet *active_set, MsqError &err)
void get_gradient_projections(MsqError &err)
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output. 
#define MSQ_CHECK_Y_COORD_DIRECTION
object is in an invalid state 
NonSmoothSteepestDescent(ObjectiveFunction *of)
#define MSQ_FUNCTION_TIMER(NAME)
int improvement_check(MsqError &err)
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag. 
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. 
void compute_alpha(MsqError &err)
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function. 
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom
virtual void optimize_vertex_positions(PatchData &pd, MsqError &err)
#define MSQ_IMP_TOO_SMALL
Base class for concrete Objective Functions ObjectiveFunction contains a pointer to a QualityMetric...
void init_max_step_length(MsqError &err)
#define MSQ_COPY_VECTOR(a, b, n)
void copy_active(ActiveSet *active1, ActiveSet *active2, MsqError &err)
void print_active_set(ActiveSet *active_set, double *func, MsqError &err)