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)