\chapter{Mesquite Features}

  This chapter is summarizes various aspects of Mesquite that will be useful in understanding the topics that follow.

\section{Solvers}

Many of the quality improvers in Mesquite work by minimizing the value of an
objective function (see Section \ref{sec:ObjectiveFunction}), where the
objective function is a function of the mesh vertex coordinates. 
The term \emph{solver} is often used to refer to the portion of the code in
the concrete subclass of \texttt{VertexMover} that implements the inner loop
of the optimization for quality improvers that optimize an explicit 
objective-function based (the code that implements the function-minimization algorithm.)

The remainder of this section lists the solvers available in Mesquite along with a small code example for each showing how to invoke the solver.


\subsection{Relaxation Smoothers}

Note that the relaxation smoothers do NOT require an objective function.

\subsubsection{LaplacianSmoother} 

Implements the Laplacian smoothing for a patch with one free vertex.  It moves the free center vertex to the average of the neighboring vertices.

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main(int argc, char* argv[])
{
  const char input_file[] = MESH_FILES_DIR "2D/vtk/quads/untangled/square_quad_2.vtk";

    /* Read a VTK Mesh file */
  MsqPrintError err(cout);
  Mesquite::MeshImpl mesh;
  mesh.read_vtk( input_file, err);
  if (err) return 1;
  
    // creates an intruction queue
  InstructionQueue queue1;
  
    // creates a mean ratio quality metric ...
  ConditionNumberQualityMetric shape_metric;
  EdgeLengthQualityMetric lapl_met;
  lapl_met.set_averaging_method(QualityMetric::RMS);
 
    // creates the laplacian smoother  procedures
  LaplacianSmoother lapl1;
  QualityAssessor stop_qa=QualityAssessor(&shape_metric);
  stop_qa.add_quality_assessment(&lapl_met);
  
    //**************Set stopping criterion****************
  TerminationCriterion sc2;
  sc2.add_iteration_limit( 10 );
  if (err) return 1;
  lapl1.set_outer_termination_criterion(&sc2);
  
  queue1.add_quality_assessor(&stop_qa,err); 
  if (err) return 1;
  queue1.set_master_quality_improver(&lapl1, err); 
  if (err) return 1;
  queue1.add_quality_assessor(&stop_qa,err); 
  if (err) return 1;
 
  PlanarDomain plane(Vector3D(0,0,1), Vector3D(0,0,5));
  
    // launches optimization on mesh
  MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &plane);
  queue1.run_instructions(&mesh_and_domain, err); 
  if (err) return 1;

  return 0;
}
\end{lstlisting}

\subsubsection{SmartLaplacianSmoother}

Does same as the Laplacian smoother, but doesn't invert elements.  Invoked same way as the LaplacianSmoother.  If initial mesh in non-inverted, the SmartLaplacianSmoother performs Laplace smoothing while trying not to invert the mesh.

\subsubsection{Randomize}

The randomize smoother moves a free vertex to a random location within a local patch.  This smoother is provided as a convenience to
those who wish to generate a poor quality mesh from an initial mesh in order to test another mesh improvement algorithm.

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main( )
{
  Mesquite::MeshImpl mesh;
  MsqPrintError err(cout);
  mesh.read_vtk(VTK_2D_DIR "quads/untangled/tangled_quad.vtk", err);
  if (err) return 1;
  
  // Set Domain Constraint
  Vector3D pnt(0,0,0);
  Vector3D s_norm(0,0,1);
  PlanarDomain msq_geom(s_norm, pnt);
                                                                              
    // creates an intruction queue
  InstructionQueue queue1;
  
  Randomize rand(.05);
  
  TerminationCriterion sc_rand;
  sc_rand.add_iteration_limit( 10 );
 
  rand.set_outer_termination_criterion(&sc_rand);
  
  queue1.set_master_quality_improver(&rand, err);
  if (err) return 1;

  MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &msq_geom);
  queue1.run_instructions(&mesh_and_domain, err);
  if (err) return 1;
  
  return 0;
}
\end{lstlisting}


\subsection{OptSolvers}

\subsubsection{ConjugateGradient}

Optimizes the objective function using the Polack-Ribiere scheme.

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main( )
{
  Mesquite::MeshImpl mesh;
  MsqPrintError err(cout);
  mesh.read_vtk(VTK_2D_DIR "quads/untangled/tangled_quad.vtk", err);
  if (err) return 1;
  
    // Set Domain Constraint
  Vector3D pnt(0,0,0);
  Vector3D s_norm(0,0,1);
  PlanarDomain msq_geom(s_norm, pnt);
                                                                              
    // creates an intruction queue
  InstructionQueue queue1;
  
    // creates a mean ratio quality metric ...
  ConditionNumberQualityMetric shape_metric;
  UntangleBetaQualityMetric untangle(2);

  LInfTemplate obj_func(&untangle);

  if (err) return 1;
    // creates the steepest descent optimization procedures
  ConjugateGradient cg( &obj_func, err );
  if (err) return 1;
  
  QualityAssessor stop_qa=QualityAssessor(&shape_metric);
  QualityAssessor stop_qa2=QualityAssessor(&shape_metric);
   
  stop_qa.add_quality_assessment(&untangle);

  queue1.add_quality_assessor(&stop_qa,err); 
  if (err) return 1;
 
  queue1.set_master_quality_improver(&cg, err);
  if (err) return 1;
  queue1.add_quality_assessor(&stop_qa2,err);
  if (err) return 1;

  MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &msq_geom);
  queue1.run_instructions(&mesh_and_domain, err);
  if (err) return 1;
  
  return 0;
}
\end{lstlisting}


\subsubsection{FeasibleNewton}
Implements the newton non-linear programming algorithm in order to move a free vertex to an optimal position given an ObjectiveFunction object and a QualityMetric object.  This implementation of Feasible Newton works well on volume meshes and on surfaces meshes using PlanarDomain that lie in the X-Y coordinate plane. It should not be used on non-planar surface meshes.

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main()
{     
  MsqPrintError err(cout);
  Mesquite::MeshImpl mesh;
  mesh.read_vtk(MESH_FILES_DIR "3D/vtk/tets/untangled/tire.vtk", err);
  if (err) return 1;
  
    // creates an intruction queue
  InstructionQueue queue1;

    // creates a mean ratio quality metric ...
  IdealWeightInverseMeanRatio mean(err);
  if (err) return 1;
  
  LPtoPTemplate obj_func(&mean, 1, err);
  if (err) return 1;
  
    // creates the optimization procedures
  FeasibleNewton fn( &obj_func );

    //perform optimization globally
  fn.use_global_patch();
  if (err) return 1;
  
  queue1.set_master_quality_improver(&fn, err); 
  if (err) return 1;

  queue1.run_instructions(&mesh, err); 
  if (err) return 1;
  
  return 0;
}
\end{lstlisting}


\subsubsection{SteepestDescent}
A very basic implementation of the steepest descent optimization algorithm.  It works on patches of any size but the step size is automatically computed and is not accessible through the interface. It is for testing purposes only. 

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main()
{
  MsqPrintError err(std::cout);
  Mesquite::MeshImpl mesh;
  mesh.read_vtk(MESH_FILES_DIR 
            "3D/vtk/hexes/untangled/hexes_4by2by2.vtk", err);
  
    // creates an instruction queue
  InstructionQueue queue1;
  
    // creates a mean ratio quality metric ...
  IdealWeightInverseMeanRatio mean_ratio(err);
  if (err) return 1;
  ConditionNumberQualityMetric cond_num;
  mean_ratio.set_averaging_method(QualityMetric::LINEAR);
  
    // ... and builds an objective function with it
  LPtoPTemplate obj_func(&mean_ratio, 2, err);
  if (err) return 1;

   // creates the steepest descent optimization procedures
  SteepestDescent sd( &obj_func );
  sd.use_global_patch();
  
  QualityAssessor stop_qa=QualityAssessor(&mean_ratio);
  if (err) return 1;
  stop_qa.add_quality_assessment(&cond_num);
  if (err) return 1;
    
   //**************Set stopping criterion****************
  TerminationCriterion tc2;
  tc2.add_iteration_limit( 1 );
  sd.set_inner_termination_criterion(&tc2);

  queue1.add_quality_assessor(&stop_qa,err);
  queue1.set_master_quality_improver(&sd, err); 
  if (err) return 1;
  queue1.add_quality_assessor(&stop_qa,err);
  if (err) return 1;

  mesh.write_vtk("original_mesh.vtk", err); 
  if (err) return 1;
  
  queue1.run_instructions(&mesh, err);
  if (err) return 1;
  

  return 0;
}
\end{lstlisting}

\subsubsection{NonGradient}
The NonGradient class is a concrete vertex mover which performs derivative free minimization based on the Amoeba Method, as implemented in Numerical Recipes in C.  It can be used with any Objective Function template and metric, but is particularly helpful when the Objective Function is non-differentiable, as in the MAX template. In fact, it is strongly reccommended that the MaxTemplate class only be used with the NonGradient solver.  Using the MaxTemplate class with any other solver class can produce less than optimal results. Mesquite will issue a warning if the MaxTemplate class is used with any solver other than NonGradient.  

NonGradient can only handle patches containing exactly one free vertex. To create a PatchSet with one free vertex per patch, call the 'use\_element\_on\_vertex\_patch()' member function of the NonGradient class as shown in the example below. 

The NonGradient class can be used with both Non-barrier and Barrier metrics. The code sample below shows how it is used with a Barrier metric.  An example of using it with a Non-barrier metric can be found in the nongradient\_test in the Mesquite testSuite.

\begin{lstlisting}[frame=single]
int main()
{
  MsqPrintError err(std::cout);
  PlanarDomain xyPlane(PlanarDomain::XY, -5);

  #define FILE_NAME "bad_circle_tri.vtk"
  const char file_name[] = MESH_FILES_DIR "2D/vtk/tris/untangled/" FILE_NAME;

    // Barrier / Max Objective Function Test

  Mesquite::MeshImpl mesh_max;
  mesh_max.read_vtk(file_name, err);
  if (err)
  {
    std::cerr << "Failed to read file." << std::endl;
    return 1;
  }

  IdealShapeTarget target_max;
  TShapeB1 mu;
  TQualityMetric tqMetric_max( &target_max, &mu );

  ElementQM* metricPtr_max;
  ObjectiveFunctionTemplate* objFunctionPtr_max;

  ElementMaxQM maxMetric( &tqMetric_max );
  MaxTemplate maxObjFunction(&maxMetric);  // max(max)

  LPtoPTemplate PtoPObjMaxfunction(&maxMetric, 1.0, err);  // max(max)

  // Processing for Max Objective Function

  NonGradient max_opt( &maxObjFunction ); // optimization procedure 

  max_opt.setSimplexDiameterScale(0);
  max_opt.use_element_on_vertex_patch(); // local patch
  max_opt.set_debugging_level(0);

  // Construct and register the Quality Assessor instances
  QualityAssessor max_initial_qa=QualityAssessor(&maxMetric, 10);
  QualityAssessor maxObj_max_optimal_qa=QualityAssessor(&maxMetric, 10);

  //**************Set stopping criterion****************
  TerminationCriterion innerTC, outerTC;

  outerTC.add_iteration_limit(40);
  innerTC.add_iteration_limit(20);
  max_opt.set_outer_termination_criterion(&outerTC);
  max_opt.set_inner_termination_criterion(&innerTC);
  Mesquite::MeshDomainAssoc mesh_and_domain 
                               = MeshDomainAssoc(&mesh_max, &xyPlane);
  queue1.run_instructions(&mesh_and_domain, err);
  if (err) return 1;

  return 0;
}

\end{lstlisting}

\subsubsection{QuasiNewton}
Port of Todd Munson's quasi-Newton solver to Mesquite.

\textbf{Code Example:}

\begin{lstlisting}[frame=single]
int main()
{
  MsqPrintError err(std::cout);
  Mesquite::MeshImpl mesh;
  mesh.read_vtk(MESH_FILES_DIR "3D/vtk/hexes/untangled/hexes_4by2by2.vtk", err);
  
    // creates an intruction queue
  InstructionQueue queue1;
  
    // creates a mean ratio quality metric ...
  IdealWeightInverseMeanRatio mean_ratio(err);
  if (err) return 1;
  EdgeLengthQualityMetric cond_num;
  mean_ratio.set_averaging_method(QualityMetric::LINEAR);
  
    // build an objective function
  LPtoPTemplate obj_func(&mean_ratio, 2, err);
  if (err) return 1;

  QuasiNewton qn( &obj_func );
  qn.use_global_patch();
  
  QualityAssessor stop_qa=QualityAssessor(&mean_ratio);
  if (err) return 1;
  stop_qa.add_quality_assessment(&cond_num);
  if (err) return 1;
    
   //**************Set stopping criterion****************
  TerminationCriterion tc2;
  tc2.add_iteration_limit( 1 );
  qn.set_inner_termination_criterion(&tc2);

  queue1.add_quality_assessor(&stop_qa,err);
  queue1.set_master_quality_improver(&qn, err); 
  if (err) return 1;
  queue1.add_quality_assessor(&stop_qa,err);
  if (err) return 1;

  queue1.run_instructions(&mesh, err);
  if (err) return 1;
  
  return 0;
}
\end{lstlisting}


\subsubsection{TrustRegion}
Port of Todd Munson's trust region solver to Mesquite.  The TrustRegion optimizer is invoked in the same way as in the previous QuasiNewton example.


\section{Objective Function}
\label{sec:ObjectiveFunction}

\subsection{Definition}

An objective function is a scalar function of all the vertex coordinates in the active mesh.  The mesh vertex locations are optimized so as to minimize the objective function value.  

The objective functions implemented in Mesquite can be divided into two general categories: template objective functions and composite objective functions.  Template objective functions have an associated \texttt{QualityMetric} instance and typically implement some kind of averaging scheme.  Composite objective functions modify the values of one or two other objective functions, such as scaling the value or summing two values.

Most solvers in Mesquite also require the gradient of the objective function (the partial derivatives of the objective function with respect to the coordinate values of the free vertices in the patch.)  

\label{sec:Hessian} Some quality improvers (currently \texttt{FeasibleNewton}) need to know the Hessian (second partial derivatives) of the objective function.  Only an \texttt{ObjectiveFunction} implementation capable of providing Hessian data may be used with such a solver.  Mesquite provides numerical approximation of objective function gradient values, and of quality metric gradient and Hessian values, but not objective function Hessian values.  Further, Mesquite is capable of working only with Hessians of objective functions that have sparse Hessian matrices.  The Hessian matrix may only contain non-zero terms for vertex pairs that share at least one element.  This limitation is explicit in the implementation of the \texttt{MsqHessian} class, and is implicit in other areas of the code (such as portions of the \texttt{ObjectiveFunction} interface relating to use in a BCD algorithm.)  Some \texttt{ObjectiveFunction} implementations such as \texttt{CompositeOFMultiply} (the product of two other objective function values) and \texttt{StdDevTemplate} have a dense Hessian and therefore cannot be used with solvers requiring a Hessian.

Objective Functions can be used with all \texttt{QualityMetric} classes and with the target metric classes (\texttt{TMetric} and \texttt{AWMetric}). When using a Barrier Metric derived from \texttt{TMetricBarrier} or \texttt{AWMetricBarrier}, the mesh to be optimized cannot contain inverted elements.  Any attempt to use an objective function on an inverted mesh with a barrier target metric will cause Mesquite to terminate execution with a BARRIER\_VIOLATED error.

\subsection{Objective Function Implementations}
\label{sec:objfunc_impl}

The \texttt{ObjectiveFunctionTemplate} is a base class for those objective function implementations that are some kind of average of quality metric values.  The \texttt{ObjectiveFunctionTemplate} class provides the API for associating a \texttt{QualityMetric} with an objective function and it provides a common implementation for initializing coordinate descent optimizations.

The composite objective functions modify one or two existing objective functions (e.g. adding two together).  All composite \texttt{ObjectiveFunction}s support analytical gradients and coordinate descent optimization if the underlying \texttt{ObjectiveFunction}s do.  Similarly, all except \texttt{CompositeOFMultiply} support analytical Hessians as long as their underlying \texttt{ObjectiveFunction}s do.  \texttt{CompositeOFMultiply} does not have a suitably sparse Hessian.

Two of the most commonly used objective functions are:

\begin{description}
\item[LPtoPTemplate] - Calculates the L\_p objective function raised to the pth power.
    That is, it sums the p-th powers of (the absolute value of) the quality metric values.

\item[PMeanPTemplate] - This class implements an objective function that is the power-mean
    of the quality metric evaluations raised to the power-mean power.  That is, the sum of 
   each quality metric value raised to a power, divided by the total number of quality 
   metric values.
\end{description}

\subsection{Example}

Below is a simplified version of the ShapeImprover Wrapper that has been annotated to illustrate the use of an objective function.

\begin{lstlisting}[frame=single]

void ShapeImprover::run_wrapper( MeshDomainAssoc* mesh_and_domain,
                                 ParallelMesh* pmesh,
                                 Settings* settings,
                                 QualityAssessor* qa,
                                 MsqError& err )
{
    // Quality Metrics

    // Used to obtain a target matrix for the quality assessment. Creates a
    // target matrix based on the element type and its ideal shape
  IdealShapeTarget target;

    // Local sample point quality metric is TShapeB1, a shape metric 
    // with barrier
  TShapeB1 mu;

    // A quality metric defined using 2D and 3D target metrics, where 
    // the active matrix compared to the target by the underlying 
    // metrics is the Jacobian matrix of the mapping function at a 
    // given sample point. Evaluates the quality metric at the sample
    // point by forming T in terms of the active and target matrices.
  TQualityMetric metric_0( &target, &mu );

    // A composite metric that converts the sample-based metric 
    // (metric_0) to an element-based metric by averaging the metric
    //  values at each sample point within the element
  ElementPMeanP metric( 1.0, &metric_0 );

    // QualityAssessor
  qa->add_quality_assessment( &metric );
    
    // an objective function that is the power-mean of the 
    // quality metric evaluations raised to the power-mean power.
  PMeanPTemplate obj_func( 1.0, &metric );

    // Optimizes the objective function using the Polack-Ribiere scheme.
  ConjugateGradient improver( &obj_func );

    // Treat the mesh as a single patch
  improver.use_global_patch();
  TerminationCriterion inner;
  inner.add_absolute_vertex_movement_edge_length( 0.005 );
  improver.set_inner_termination_criterion( &inner );
  InstructionQueue q;
  q.set_master_quality_improver( &improver, err ); MSQ_ERRRTN(err);
  q.add_quality_assessor( qa, err ); MSQ_ERRRTN(err);
  q.run_common( mesh_and_domain, pmesh, settings, err ); MSQ_ERRRTN(err);
}

\end{lstlisting}

In the above example, the quality metric TShapB1 can be replaced by any of the many quality metrics that are derived from the TMetric class.

\section{\texttt{MsqError}}
\label{sec:MsqError}

Almost every function in the Mesquite API accepts an instance of the \texttt{MsqError} class and uses that instance to flag the occurance of any errors.  For brevity, this argument is not shown or discussed for any function in the API.  The reader may assume an implicit final argument of type \texttt{MsqError\&} for almost every function shown or discussed in this document, the exceptions being those functions that cannot fail.

The \texttt{MsqError} class can be treated as a Boolean, where a true state indicates an error.  It can also be sent to a C++ output stream to print the error code, error message, and call stack (trace of nested function calls beginning with the topmost API call down to the function at which the error occured.)  An application will typically use an \texttt{MsqError} as follows:
\begin{lstlisting}
if (err) {
  std::cout << err << std::endl;
  return FAILURE;
}
\end{lstlisting}
The \texttt{MsqError} class also provides functions to progamatically extract data from such as the error message, error code, and call stack lines.

Mesquite also provides several macros to assist developers in using the \texttt{MsqError} class within Mesquite.  The \texttt{MSQ\_SETERR} macro is used to flag an initial error condition.  The following examples show typical uses of this macro:
\begin{lstlisting}
  // literal error message and error code
MSQ_SETERR(err)( "My error message", MsqError::UNKNOWN_ERROR );
  // error code and printf-style formatted error message
MSQ_SETERR(err)( MsqError::INVALID_ARG, "Argument 'foo' = %d", foo );
  // error code and default message for that error code
MSQ_SETERR(err)( MsqError::OUT_OF_MEMORY );
\end{lstlisting}

The \texttt{MSQ\_CHKERR} macro evalutes to true if an error has been flagged, and false otherwise.  Further, if an error has been flagged, it appends the location of the \texttt{MSQ\_CHKERR} invokation to the call stack maintained in the \texttt{MsqError} instance.  This is the mechanism by which Mesquite generates the call-stack data.  The following is an example of how this macro is typically used:
\begin{lstlisting}
  if (MSQ_CHKERR(err))
    return FAILURE;
\end{lstlisting}
The macro may also seen used similar to the following example:
\begin{lstlisting}
  return !MSQ_CHKERR(err) && result_bool;
\end{lstlisting}
This statement will result in a return value of \texttt{false} if either an error has been flaged or \texttt{result\_bool} is false.  The order of the tests is important in this example.  The \texttt{MSQ\_CHKERR} macro must occur first so that the call stack is updated, regardless of the value of \texttt{result\_bool}.

\texttt{MSQ\_ERRRTN} and \texttt{MSQ\_ERRZERO}  are convenience macros for developers. They are defined as follows:
\begin{lstlisting}
 #define MSQ_ERRRTN(ERR)  if (MSQ_CHKERR(ERR)) return
 #define MSQ_ERRZERO(ERR) if (MSQ_CHKERR(ERR)) return 0
\end{lstlisting}

