Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Control/TerminationCriterion.cpp
Go to the documentation of this file.
1 /* *****************************************************************
2  MESQUITE -- The Mesh Quality Improvement Toolkit
3 
4  Copyright 2004 Sandia Corporation and Argonne National
5  Laboratory. Under the terms of Contract DE-AC04-94AL85000
6  with Sandia Corporation, the U.S. Government retains certain
7  rights in this software.
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  (lgpl.txt) along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 
23  diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
24  pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
25 
26  ***************************************************************** */
27 // -*- Mode : c++; tab-width: 2; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 2 -*-
28 //
29 // DESCRIPTION:
30 // ============
40 #include "TerminationCriterion.hpp"
41 #include "MeshSet.hpp"
42 #include "MsqVertex.hpp"
43 #include "MsqInterrupt.hpp"
44 #include "ObjectiveFunction.hpp"
45 #include "MsqError.hpp"
46 #include "MsqDebug.hpp"
47 
48 namespace Mesquite {
49 
50 
59 
63  : mGrad(8),
64  initialVerticesMemento(0),
65  previousVerticesMemento(0),
66  debugLevel(2)
67 {
70  cullingEps=0.0;
71  initialOFValue=0.0;
72  previousOFValue=0.0;
73  currentOFValue = 0.0;
74  lowerOFBound=0.0;
77  //initial size of the gradient array
86  timeBound=0.0;
92 
93 }
94 
95 
96 
101  double eps,
102  MsqError &err)
103 {
104  switch(tc_type){
108  break;
112  break;
116  break;
120  break;
124  break;
128  break;
129  case CPU_TIME:
131  timeBound=eps;
132  break;
135  //we actually compare squared movement to squared epsilon
136  vertexMovementAbsoluteEps=(eps*eps);
137  break;
140  //we actually compare squared movement to squared epsilon
141  vertexMovementRelativeEps=(eps*eps);
142  break;
146  break;
150  break;
154  break;
155  default:
156  MSQ_SETERR(err)("TCType not valid for this function.",MsqError::INVALID_ARG);
157  };
158 }
159 
164  int bound,
165  MsqError &err)
166 {
167  switch(tc_type){
168  case NUMBER_OF_ITERATES:
170  iterationBound=bound;
171  break;
172  default:
173  MSQ_SETERR(err)("TCType not valid for this function.",MsqError::INVALID_ARG);
174  };
175 }
178  MsqError &/*err*/)
179 {
180  terminationCriterionFlag&=(~tc_type);
181 }
182 
183 
189  MsqError &err)
190 {
191  switch(tc_type){
194  break;
197  break;
200  break;
203  break;
206  break;
209  break;
210  default:
211  MSQ_SETERR(err)("TCType not valid for this function.",MsqError::INVALID_ARG);
212  };
213  cullingEps=eps;
214 }
215 
218 {
220 }
221 
222 
223 
229  MsqError &err)
230 {
231  const unsigned long totalFlag = terminationCriterionFlag | cullingMethodFlag;
232  PatchData global_patch;
233 
234  //if we need to fill out the global patch data object.
235  if (totalFlag & (GRAD_FLAGS | OF_FLAGS | VERTEX_MOVEMENT_RELATIVE))
236  {
237  PatchDataParameters global_patch_params;
238  global_patch_params.set_patch_type( PatchData::GLOBAL_PATCH, err, 0, 0 );
239  MSQ_ERRRTN(err);
240  ms.get_next_patch( global_patch, global_patch_params, err );
241  MSQ_ERRRTN(err);
242  }
243 
244  //now call the other reset
245  reset_inner( global_patch, obj_ptr, err ); MSQ_ERRRTN(err);
246 }
247 
266  MsqError &err)
267 {
268  const unsigned long totalFlag = terminationCriterionFlag | cullingMethodFlag;
269  OFPtr = obj_ptr;
270 
271  // clear flag for BOUNDED_VERTEX_MOVEMENT
273 
274  // Use -1 to denote that this isn't initialized yet.
275  // As all valid values must be >= 0.0, a negative
276  // value indicates that it is uninitialized and is
277  // always less than any valid value.
278  maxSquaredMovement = -1;
279 
280  // Clear the iteration count.
281  iterationCounter = 0;
282 
283  //reset the inner timer if needed
284  if(totalFlag & CPU_TIME){
285  mTimer.reset();
286  }
287 
288  //GRADIENT
289  if(totalFlag & GRAD_FLAGS)
290  {
291  int num_vertices=pd.num_vertices();
292  mGrad.resize( num_vertices );
293 
294  //get gradient and make sure it is valid
295  bool b = obj_ptr->compute_gradient(pd, &mGrad[0] , currentOFValue,
296  err, num_vertices); MSQ_ERRRTN(err);
297  if (!b) {
298  MSQ_SETERR(err)("Initial patch is invalid for gradient computation.",
300  return;
301  }
302 
303  //get the gradient norms
305  {
306  currentGradInfNorm = initialGradInfNorm = Linf(&mGrad[0], num_vertices);
307  MSQ_DBGOUT(debugLevel) << " o Initial gradient Inf norm: "
308  << initialGradInfNorm << msq_stdio::endl;
309  }
311  {
312  currentGradL2Norm = initialGradL2Norm = length(&mGrad[0], num_vertices);
313  MSQ_DBGOUT(debugLevel) << " o Initial gradient L2 norm: "
314  << initialGradL2Norm << msq_stdio::endl;
315  }
316  //the OFvalue comes for free, so save it
319  }
320  //find the initial objective function value if needed and not already
321  //computed. If we needed the gradient, we have the OF value for free.
322  else if (totalFlag & OF_FLAGS)
323  {
324  //ensure the obj_ptr is not null
325  if(obj_ptr==NULL){
326  MSQ_SETERR(err)("Error termination criteria set which uses objective "
327  "functions, but no objective function is available.",
329  return;
330  }
331 
332  bool b = obj_ptr->evaluate(pd, currentOFValue, err); MSQ_ERRRTN(err);
333  if (!b){
334  MSQ_SETERR(err)("Initial patch is invalid for evaluation.",MsqError::INVALID_STATE);
335  return;
336  }
337  //std::cout<<"\nReseting initial of value = "<<initialOFValue;
340  }
341 
342  if (totalFlag & (GRAD_FLAGS|OF_FLAGS))
343  MSQ_DBGOUT(debugLevel) << " o Initial OF value: " << initialOFValue << msq_stdio::endl;
344 
345  // Store current vertex locations now, because we'll
346  // need them later to compare the current movement with.
347  if (totalFlag & VERTEX_MOVEMENT_RELATIVE)
348  {
350  {
352  }
353  else
354  {
356  }
357  MSQ_ERRRTN(err);
358  maxSquaredInitialMovement = DBL_MAX;
359  }
360 }
361 
363 {
364  const unsigned long totalFlag = terminationCriterionFlag | cullingMethodFlag;
366  {
369  else
371  MSQ_ERRRTN(err);
372  }
373 }
374 
376 {
377  double of_value = 0;
378 
380  {
381  mGrad.resize( pd.num_vertices() );
382  bool b = OFPtr->compute_gradient(pd, &mGrad[0], of_value, err, pd.num_vertices());
383  MSQ_ERRRTN(err);
384  if (!b) {
385  MSQ_SETERR(err)("Initial patch is invalid for gradient compuation.",
387  return;
388  }
389  }
391  {
392  bool b = OFPtr->evaluate(pd, of_value, err); MSQ_ERRRTN(err);
393  if (!b) {
394  MSQ_SETERR(err)("Invalid patch passed to TerminationCriterion.",
396  return;
397  }
398  }
399 
400  accumulate_inner( pd, of_value, &mGrad[0], err ); MSQ_CHKERR(err);
401 }
402 
403 
405  double of_value,
406  Vector3D* grad_array,
407  MsqError& err )
408 {
409  //if terminating on the norm of the gradient
410  currentGradL2Norm = 10e6;
412  {
413  currentGradL2Norm = length(grad_array, pd.num_vertices()); // get the L2 norm
414  MSQ_DBGOUT(debugLevel) << " o TermCrit -- gradient L2 norm: "
415  << currentGradL2Norm << msq_stdio::endl;
416  }
417  currentGradInfNorm = 10e6;
419  {
420  currentGradInfNorm = length(grad_array, pd.num_vertices()); // get the Linf norm
421  MSQ_DBGOUT(debugLevel) << " o TermCrit -- gradient Inf norm: "
422  << currentGradInfNorm << msq_stdio::endl;
423  }
424 
426  {
428  initialVerticesMemento, err ); MSQ_ERRRTN(err);
429  }
430 
432  currentOFValue = of_value;
434  MSQ_DBGOUT(debugLevel) << " o TermCrit -- OF Value: " << of_value << msq_stdio::endl;
435  else if (grad_array)
436  MSQ_DBGOUT(debugLevel) << " o OF Value: " << of_value << msq_stdio::endl;
437 
439 }
440 
441 
443 {
444  PatchData global_patch;
445 
446  //if we need to fill out the global patch data object.
448  {
449  PatchDataParameters global_params;
450  global_params.set_patch_type( PatchData::GLOBAL_PATCH, err, 0, 0 );MSQ_ERRRTN(err);
451  ms.get_next_patch( global_patch, global_params, err ); MSQ_ERRRTN(err);
452  }
453 
454  accumulate_inner( global_patch, err ); MSQ_ERRRTN(err);
455 }
456 
457 
459 {
461  {
462  double patch_max_dist = pd.get_max_vertex_movement_squared( previousVerticesMemento, err );
463  if (patch_max_dist > maxSquaredMovement)
464  maxSquaredMovement = patch_max_dist;
466  }
467 
468  //if terminating on bounded vertex movement (a bounding box for the mesh)
470  {
471  MsqVertex* vert = pd.get_vertex_array(err);
472  int num_vert = pd.num_vertices();
473  int i=0;
474  //for each vertex
475  for(i=0;i<num_vert;++i)
476  {
477  //if any of the coordinates are greater than eps
478  if( (vert[i][0]>boundedVertexMovementEps) ||
479  (vert[i][1]>boundedVertexMovementEps) ||
480  (vert[i][2]>boundedVertexMovementEps) )
481  {
483  }
484  }
485  }
486 }
487 
488 
494 {
495  bool return_flag = false;
496  // cout<<"\nInside terminate(pd,of,err): flag = "<<terminationCriterionFlag << endl;
497 
498  //First check for an interrupt signal
500  {
501  MSQ_DBGOUT(debugLevel) << " o TermCrit -- INTERRUPTED" << msq_stdio::endl;
502  return true;
503  }
504 
505  //if terminating on numbering of inner iterations
508  {
509  return_flag = true;
510  MSQ_DBGOUT(debugLevel) << " o TermCrit -- Reached " << iterationBound << " iterations." << msq_stdio::endl;
511  }
512 
514  {
515  return_flag=true;
516  MSQ_DBGOUT(debugLevel) << " o TermCrit -- Exceeded CPU time." << msq_stdio::endl;
517  }
518 
519 
521  && maxSquaredMovement >= 0.0)
522  {
523  MSQ_DBGOUT(debugLevel) << " o TermCrit -- Maximuim vertex movement: "
524  << sqrt(maxSquaredMovement) << msq_stdio::endl;
525 
528  {
529  return_flag = true;
530  }
531 
534  {
535  return_flag = true;
536  }
537 
538  // Clear this value at the end of each iteration.
539  maxSquaredMovement = -1.0;
540  }
541 
544  {
545  return_flag = true;
546  }
547 
550  {
551  return_flag = true;
552  }
553 
556  {
557  return_flag = true;
558  }
559 
562  {
563  return_flag = true;
564  }
565 
568  {
569  return_flag = true;
570  }
571 
575  {
576  return_flag = true;
577  }
578 
581  {
582  return_flag = true;
583  }
584 
588  {
589  return_flag = true;
590  }
591 
593  {
594  return_flag = true;
595  MSQ_DBGOUT(debugLevel) << " o TermCrit -- " << vertexMovementExceedsBound
596  << " vertices out of bounds." << msq_stdio::endl;
597  }
598 
599  // clear this value at the end of each iteration
601 
602  //if none of the criteria were satisfied
603  return return_flag;
604 }
605 
606 
607 
608 
619  ObjectiveFunction* obj_ptr,
620  MsqError &err)
621 {
622  //PRINT_INFO("CULLING_METHOD FLAG = %i",cullingMethodFlag);
623 
624  //cull_bool will be changed to true if the criterion is satisfied
625  bool b, cull_bool=false;
626  double prev_m, init_m;
627  switch(cullingMethodFlag){
628  //if no culling is requested, always return false
629  case NONE:
630  return cull_bool;
631  //if culling on quality improvement absolute
633  //get objective function value
634  b = obj_ptr->evaluate(pd, currentOFValue, err);
635  if (MSQ_CHKERR(err)) return false;
636  if (!b) {
638  return false;
639  }
640  //if the improvement was enough, cull
642  {
643  cull_bool=true;
644  }
645  //PRINT_INFO("\ncurrentOFValue = %f, bool = %i\n",currentOFValue,cull_bool);
646 
647  break;
648  //if culing on quality improvement relative
650  //get objective function value
651  b = obj_ptr->evaluate(pd, currentOFValue, err);
652  if (MSQ_CHKERR(err)) return false;
653  if(!b){
655  return false;
656  }
657  //if the improvement was enough, cull
660  {
661  cull_bool=true;
662  }
663  break;
664  //if culling on vertex movement absolute
666  //if movement was enough, cull
668  MSQ_ERRZERO(err);
669  if(prev_m <= cullingEps){
670  cull_bool=true;
671  }
672 
673  break;
674  //if culling on vertex movement relative
676  //if movement was small enough, cull
678  MSQ_ERRZERO(err);
680  MSQ_ERRZERO(err);
681  if(prev_m <= (cullingEps * init_m)){
682  cull_bool=true;
683  }
684  break;
685  default:
686  MSQ_SETERR(err)("Requested culling method not yet implemented.",
688  return false;
689  };
690  //Now actually have patch data cull vertices
691  if(cull_bool)
692  {
694  }
695  else
696  {
698  }
699  return cull_bool;
700 }
701 
708 {
710  delete initialVerticesMemento;
713 
714  if(cullingMethodFlag){
716  }
717 }
718 
719 } //namespace Mesquite
void set_free_vertices_soft_fixed(MsqError &err)
Add a soft_fixed flag to all free vertices in the patch.
Terminates when a the maximum distance moved by any vertex during the previous iteration is below the...
const unsigned long GRAD_FLAGS
static bool interrupt()
Check if an interrupt was seen.
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
double get_max_vertex_movement_squared(PatchDataVerticesMemento *memento, MsqError &err)
Calculates the distance each vertex has moved from its original position as defined by the PatchDataV...
Terminates when the decrease in the objective function value since the previous iteration is below th...
void set_patch_type(PatchData::PatchType patch_type, MsqError &err, int patch_param1=0, int patch_param2=0)
Tells the MeshSet what kind of data the patches should include.
void cleanup(MeshSet &ms, MsqError &err)
Cleans up after the TerminationCriterion is finished.
void set_all_vertices_soft_free(MsqError &err)
Remove the soft_fixed flag from all vertices in the patch.
Terminates when any vertex leaves the bounding box, defined by the given value, d.
Used to hold the error state and return it to the application.
void accumulate_patch(PatchData &pd, MsqError &err)
Common code for both inner and outer termination criteria during inner iteration. ...
void recreate_vertices_memento(PatchDataVerticesMemento *memento, MsqError &err, bool include_higher_order=false)
reinstantiates a memento to holds the current state of the PatchData coordinates. ...
requested functionality is not (yet) implemented
bool evaluate(PatchData &patch, double &fval, MsqError &err)
Vector3D is the object that effeciently stores information about about three-deminsional vectors...
checks the gradient of objective function against a double and stops when
TerminationCriterion()
Constructor which does not take any arguements.
void reset_outer(MeshSet &ms, ObjectiveFunction *of, MsqError &err)
Clear any data accumulated during an outer iteration.
double sqrt(double d)
Definition: double.h:73
Terminates when a the maximum distance moved by any vertex during the previous iteration is below the...
void reset_inner(PatchData &pd, ObjectiveFunction *of, MsqError &err)
Clear any data accumulated during an inner iteration.
bool terminate()
Check if termination criterion has been met.
terminates on the j_th iteration when That is, terminates when the norm of the gradient is small tha...
bool cull_vertices(PatchData &pd, ObjectiveFunction *obj_ptr, MsqError &err)
Function which determines whether this patch should be &#39;culled&#39;.
void reset_patch(PatchData &pd, MsqError &err)
Shared inner and outer initialization during inner loop.
Terminates when the decrease in the objective function value since the previous iteration is below th...
PatchDataVerticesMemento * create_vertices_memento(MsqError &err, bool include_higher_order=false)
Creates a memento that holds the current state of the PatchData coordinates.
double length(Vector3D *const v, int n)
double since_birth() const
const unsigned long OF_FLAGS
invalid function argument passed
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
bool compute_gradient(PatchData &patch, Vector3D *const &grad, double &OF_val, MsqError &err, size_t array_size=0)
Calls either compute_numerical_gradient or compute_analytical_gradient depending on the value of grad...
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
Terminates when the objective function value is smaller than the given scalar value.
Terminates when the algorithm exceeds an allotted time limit (given in seconds).
blockLoc i
Definition: read.cpp:79
void set_culling_type(TCType tc_type, double eps, MsqError &err)
Sets the type of criterion that the user would like to use for culling purposes (along with the assoc...
void add_criterion_type_with_double(TCType tc_type, double eps, MsqError &err)
Sets the criterion by specifing the TCType and the eps value.
long unsigned int terminationCriterionFlag
Bit flag of termination crit.
double Linf(Vector3D *const v, int n)
size_t num_vertices() const
number of vertices in the patch.
void accumulate_inner(PatchData &pd, MsqError &err)
Accumulate data during inner iteration.
const MsqVertex * get_vertex_array(MsqError &err) const
Returns a pointer to the start of the vertex array.
Terminates when the number of iterations exceeds a given integer.
void remove_criterion_type(TCType tc_type, MsqError &err)
Removes the criterion by specifing just the TCType.
void remove_culling(MsqError &err)
Removes any previously set culling types (sets the culling type to be NONE).
object is in an invalid state
bool clear_all_soft_fixed_flags(MsqError &err)
void accumulate_outer(MeshSet &ms, MsqError &err)
Terminates when the objective function value is smaller than the given scalar value times the origina...
void add_criterion_type_with_int(TCType tc_type, int bound, MsqError &err)
Sets the criterion by specifing the TCType and the integer value.
checks the gradient of objective function against a double and stops when
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
MsqVertex is the Mesquite object that stores information about the vertices in the mesh...
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
Base class for concrete Objective Functions ObjectiveFunction contains a pointer to a QualityMetric...
The MeshSet class stores one or more Mesquite::Mesh pointers and manages access to the mesh informati...
bool get_next_patch(PatchData &pd, PatchDataUser *pd_user, MsqError &err)
Gets the next PatchData.