LCOV - code coverage report
Current view: top level - src/mesquite/QualityImprover/OptSolvers - NonGradient.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 156 217 71.9 %
Date: 2020-07-18 00:09:26 Functions: 13 18 72.2 %
Branches: 180 462 39.0 %

           Branch data     Line data    Source code
       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                 :            :     [email protected], [email protected], [email protected],
      24                 :            :     [email protected], [email protected], [email protected]
      25                 :            : 
      26                 :            :   ******************************************************************/
      27                 :            : /*!
      28                 :            :   \file   NonGradient.cpp
      29                 :            :   \brief
      30                 :            :   The NonGradient class is also a concrete vertex mover
      31                 :            :   which performs derivative free minimization
      32                 :            :   based on the Amoeba Method, as implemented in Numerical Recipes in C.
      33                 :            : 
      34                 :            :   The other optimization methods either accept or reject a point immediately.
      35                 :            :   Amoeba may not accept a point for several iterations/evaluations.
      36                 :            :   Amoeba does not check for BOUNDED_VERTEX_MOVERMENT.
      37                 :            :   rtol=2.0*fabs( height[ihi]-height[ilo] )/
      38                 :            :          ( fabs(height[ihi])+fabs(height[ilo])+threshold );
      39                 :            : 
      40                 :            :   We are aware of the problem of choosing the initial simplex, but have not
      41                 :            :   sovled it.  How has this been solved?
      42                 :            :   There is a problem of letting Mesquite handle convergence.  The idea here is to
      43                 :            :   call accumulate_? only if the best point changes. But does it matter?  Where
      44                 :            :   are the errors determined?  What does it mean to cull?
      45                 :            :   What does Pat... compare and contrast the differnt vertex movement criteria
      46                 :            :   with the Amoeba criterion.
      47                 :            : */
      48                 :            : 
      49                 :            : #include "NonGradient.hpp"
      50                 :            : #include "MsqFreeVertexIndexIterator.hpp"
      51                 :            : #include "MsqTimer.hpp"
      52                 :            : #include "MsqDebug.hpp"
      53                 :            : #include "MsqError.hpp"
      54                 :            : #include <cmath>
      55                 :            : #include <iostream>
      56                 :            : #include "../../ObjectiveFunction/ObjectiveFunction.hpp"
      57                 :            : #include <float.h>
      58                 :            : 
      59                 :            : namespace MBMesquite
      60                 :            : {
      61                 :            : 
      62                 :          0 : std::string NonGradient::get_name() const
      63                 :            : {
      64         [ #  # ]:          0 :     return "NonGradient";
      65                 :            : }
      66                 :            : 
      67                 :          4 : PatchSet* NonGradient::get_patch_set()
      68                 :            : {
      69                 :          4 :     return PatchSetUser::get_patch_set();
      70                 :            : }
      71                 :            : 
      72                 :          3 : NonGradient::NonGradient( ObjectiveFunction* of )
      73                 :            :     : VertexMover( of ), PatchSetUser( true ), projectGradient( false ), mDimension( 0 ), mThreshold( 0.0 ),
      74 [ +  - ][ +  - ]:          3 :       mTolerance( 0.0 ), mMaxNumEval( 0 ), mNonGradDebug( 0 ), mUseExactPenaltyFunction( true ), mScaleDiameter( 0.1 )
                 [ +  - ]
      75                 :            : {
      76         [ +  - ]:          3 :     set_debugging_level( 2 );
      77                 :            :     // set the default inner termination criterion
      78         [ +  - ]:          3 :     TerminationCriterion* default_crit = get_inner_termination_criterion();
      79         [ -  + ]:          6 :     if( default_crit == NULL ) { return; }
      80                 :            :     else
      81                 :            :     {
      82         [ +  - ]:          3 :         default_crit->add_iteration_limit( 5 );
      83                 :            :     }
      84                 :            : }
      85                 :            : 
      86                 :          0 : NonGradient::NonGradient( ObjectiveFunction* of, MsqError& err )
      87                 :            :     : VertexMover( of ), PatchSetUser( true ), projectGradient( false ), mDimension( 0 ), mThreshold( 0.0 ),
      88 [ #  # ][ #  # ]:          0 :       mTolerance( 0.0 ), mMaxNumEval( 0 ), mNonGradDebug( 0 ), mUseExactPenaltyFunction( true ), mScaleDiameter( 0.1 )
                 [ #  # ]
      89                 :            : {
      90         [ #  # ]:          0 :     set_debugging_level( 2 );
      91                 :            :     // set the default inner termination criterion
      92         [ #  # ]:          0 :     TerminationCriterion* default_crit = get_inner_termination_criterion();
      93         [ #  # ]:          0 :     if( default_crit == NULL )
      94                 :            :     {
      95                 :            :         MSQ_SETERR( err )
      96                 :            :         ( "QualityImprover did not create a default inner "
      97                 :            :           "termination criterion.",
      98 [ #  # ][ #  # ]:          0 :           MsqError::INVALID_STATE );
      99                 :          0 :         return;
     100                 :            :     }
     101                 :            :     else
     102                 :            :     {
     103 [ #  # ][ #  # ]:          0 :         default_crit->add_iteration_limit( 5 );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     104                 :            :     }
     105                 :            : }
     106                 :            : 
     107                 :          0 : bool NonGradient::testRowSum( int numRow, int numCol, double* matrix, double* oldRowSum )
     108                 :            : {
     109                 :          0 :     bool same = true;
     110         [ #  # ]:          0 :     std::vector< double > rowSum( numRow, 0. );
     111                 :          0 :     double maxVal = 0.;
     112         [ #  # ]:          0 :     for( int col = 0; col < numCol; col++ )
     113                 :            :     {
     114         [ #  # ]:          0 :         for( int row = 0; row < numRow; row++ )
     115                 :            :         {
     116         [ #  # ]:          0 :             rowSum[row] += matrix[row + col * numRow];
     117         [ #  # ]:          0 :             if( fabs( matrix[row + col * numRow] ) > maxVal ) { maxVal = fabs( matrix[row + col * numRow] ); }
     118                 :            :         }
     119                 :            :     }
     120                 :          0 :     double machEps    = 1.e-14 * static_cast< double >( numRow );  // better to use system parameters
     121                 :          0 :     double upperBound = machEps * maxVal + 1.e-15;
     122         [ #  # ]:          0 :     for( int row = 0; row < numRow; row++ )
     123                 :            :     {
     124 [ #  # ][ #  # ]:          0 :         if( fabs( rowSum[row] - oldRowSum[row] ) > upperBound )
     125                 :            :         {
     126                 :          0 :             same = false;
     127         [ #  # ]:          0 :             if( mNonGradDebug >= 2 )
     128                 :            :             {
     129 [ #  # ][ #  # ]:          0 :                 std::cout << " Warning: NonGradient Row Sum " << row << " Test: value " << rowSum[row]
         [ #  # ][ #  # ]
                 [ #  # ]
     130 [ #  # ][ #  # ]:          0 :                           << " Discrepancy " << rowSum[row] - oldRowSum[row] << " maxVal " << maxVal << " numRow "
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     131 [ #  # ][ #  # ]:          0 :                           << numRow << " numCol " << numCol << std::endl;
         [ #  # ][ #  # ]
     132                 :            :             }
     133                 :            :             MSQ_PRINT( 2 )
     134                 :            :             ( "NonGradient Row Sum [%d] Test failure: value %22.15e  difference %22.15e \n", row, rowSum[row],
     135                 :            :               rowSum[row] - oldRowSum[row] );
     136                 :            :         }
     137                 :            :     }
     138                 :          0 :     return ( same );
     139                 :            : }
     140                 :            : 
     141                 :        850 : void NonGradient::getRowSum( int numRow, int numCol, std::vector< double >& matrix, std::vector< double >& rowSum )
     142                 :            : {
     143         [ +  + ]:       2550 :     for( int row = 0; row < numRow; row++ )
     144                 :            :     {
     145                 :       1700 :         rowSum[row] = 0.;
     146                 :            :     }
     147         [ +  + ]:       3400 :     for( int col = 0; col < numCol; col++ )
     148                 :            :     {
     149         [ +  + ]:       7650 :         for( int row = 0; row < numRow; row++ )
     150                 :            :         {
     151                 :       5100 :             rowSum[row] += matrix[row + col * numRow];
     152                 :            :         }
     153                 :            :     }
     154                 :        850 : }
     155                 :            : 
     156                 :      19860 : double NonGradient::evaluate( double* point, PatchData& pd, MsqError& err )
     157                 :            : {
     158 [ +  - ][ -  + ]:      19860 :     if( pd.num_free_vertices() > 1 )
     159                 :            :     {
     160                 :            :         MSQ_SETERR( err )
     161 [ #  # ][ #  # ]:          0 :         ( "Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED );
     162                 :            :     }
     163                 :      19860 :     const size_t vertexIndex = 0;
     164 [ +  - ][ +  - ]:      19860 :     Vector3D originalVec     = pd.vertex_by_index( vertexIndex );
     165         [ +  - ]:      19860 :     Vector3D pointVec;
     166         [ +  + ]:      79440 :     for( int index = 0; index < 3; index++ )
     167                 :            :     {
     168         [ +  - ]:      59580 :         pointVec[index] = point[index];
     169                 :            :     }
     170         [ +  - ]:      19860 :     pd.set_vertex_coordinates( pointVec, vertexIndex, err );
     171         [ +  - ]:      19860 :     pd.snap_vertex_to_domain( vertexIndex, err );
     172                 :            : 
     173         [ +  - ]:      19860 :     OFEvaluator& obj_func           = get_objective_function_evaluator();
     174         [ +  - ]:      19860 :     TerminationCriterion* term_crit = get_inner_termination_criterion();
     175                 :            : 
     176                 :            :     double value;
     177         [ +  - ]:      19860 :     bool feasible = obj_func.evaluate( pd, value, err );         // MSQ_ERRZERO(err);
     178         [ +  - ]:      19860 :     term_crit->accumulate_inner( pd, value, 0, err );            // MSQ_CHKERR(err);
     179 [ +  - ][ +  + ]:      19860 :     if( err.error_code() == err.BARRIER_VIOLATED ) err.clear();  // barrier violation not an error here
                 [ +  - ]
     180 [ +  - ][ -  + ]:      19860 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     181         [ +  - ]:      19860 :     pd.set_vertex_coordinates( originalVec, vertexIndex, err );
     182 [ +  + ][ +  - ]:      19860 :     if( !feasible && mUseExactPenaltyFunction )
     183                 :            :     {  // "value" undefined btw
     184                 :       1127 :         double ensureFiniteRtol = .25;
     185                 :       1127 :         value                   = DBL_MAX * ensureFiniteRtol;
     186                 :            :         // std::cout << " Infeasible patch: " << value << std::endl; printPatch( pd, err );
     187                 :            :     }
     188                 :      19860 :     return value;
     189                 :            : }
     190                 :            : 
     191                 :            : // Extrapolate by a factor of fac through the face of the simplex
     192                 :            : // opposite the high point to a new point.  If the new point is
     193                 :            : // better, swap it with the high point.
     194                 :      15294 : double NonGradient::amotry( std::vector< double >& p_simplex, std::vector< double >& p_height, double psum[], int ihi,
     195                 :            :                             double fac, PatchData& pd, MsqError& err )
     196                 :            : {
     197         [ +  - ]:      15294 :     int numRow = getDimension();
     198                 :            :     // int numCol = numRow + 1;
     199         [ +  - ]:      15294 :     std::vector< double > ptry( numRow );  // does this make sense?
     200                 :      15294 :     double fac1 = ( 1.0 - fac ) / static_cast< double >( numRow );
     201                 :      15294 :     double fac2 = fac1 - fac;
     202         [ +  + ]:      45882 :     for( int row = 0; row < numRow; row++ )
     203                 :            :     {
     204 [ +  - ][ +  - ]:      30588 :         ptry[row] = psum[row] * fac1 - p_simplex[row + ihi * numRow] * fac2;
     205                 :            :     }
     206 [ -  + ][ #  # ]:      15294 :     if( mNonGradDebug >= 3 ) { std::cout << "Try "; }
     207                 :            :     MSQ_PRINT( 3 )( "Try" );
     208 [ +  - ][ +  - ]:      15294 :     double ytry = evaluate( &ptry[0], pd, err );  // value at trial point
     209 [ -  + ][ #  # ]:      15294 :     if( mNonGradDebug >= 3 ) { std::cout << ytry << std::endl; }
                 [ #  # ]
     210                 :            :     MSQ_PRINT( 3 )( "yTry" );
     211 [ +  - ][ +  + ]:      15294 :     if( ytry < p_height[ihi] )  // better than highest (worst)
     212                 :            :     {
     213         [ +  - ]:       3115 :         p_height[ihi] = ytry;  // swap ihi and ytry
     214         [ +  + ]:       9345 :         for( int row = 0; row < numRow; row++ )
     215                 :            :         {
     216 [ +  - ][ +  - ]:       6230 :             psum[row] += ( ptry[row] - p_simplex[row + ihi * numRow] );
     217 [ +  - ][ +  - ]:       6230 :             p_simplex[row + ihi * numRow] = ptry[row];
     218                 :            :         }
     219                 :            :     }
     220                 :      15294 :     return ytry;
     221                 :            : }
     222                 :            : 
     223                 :          0 : void NonGradient::printPatch( const PatchData& pd, MsqError& err )
     224                 :            : {
     225         [ #  # ]:          0 :     if( mNonGradDebug == 0 ) { return; }
     226                 :          0 :     const size_t numNode = pd.num_nodes();  // 27,  27 what?
     227                 :            :     MSQ_PRINT( 3 )( "Number of Vertices: %d\n", (int)pd.num_nodes() );
     228                 :          0 :     const size_t numVert = pd.num_free_vertices();  // 1
     229                 :            :     MSQ_PRINT( 3 )( "Num Free = %d\n", (int)pd.num_free_vertices() );
     230                 :          0 :     const size_t numSlaveVert = pd.num_slave_vertices();  // 0
     231                 :          0 :     const size_t numCoin      = pd.num_corners();         // 64
     232                 :          0 :     const MsqVertex* coord    = pd.get_vertex_array( err );
     233                 :            :     MSQ_PRINT( 3 )( "Number of Vertices: %d\n", (int)pd.num_nodes() );
     234                 :            : 
     235                 :          0 :     std::cout << "Patch " << numNode << "  " << numVert << "  " << numSlaveVert << "  " << numCoin << std::endl;
     236                 :            :     MSQ_PRINT( 3 )( "\n" );
     237                 :          0 :     std::cout << "Coordinate ";
     238                 :          0 :     std::cout << "         " << std::endl;
     239         [ #  # ]:          0 :     for( size_t index = 0; index < numVert; index++ )
     240                 :            :     {
     241                 :          0 :         std::cout << coord[index][0] << "  " << coord[index][1] << "  " << coord[index][2] << std::endl;
     242                 :            :     }
     243                 :            :     // const size_t numElt = pd.num_elements();
     244         [ #  # ]:          0 :     if( mNonGradDebug >= 3 ) { std::cout << "Number of Elements: " << pd.num_elements() << std::endl; }
     245                 :            :     MSQ_PRINT( 3 )( "Number of Elements: %d\n", (int)pd.num_elements() );
     246                 :            : }
     247                 :            : 
     248                 :          0 : void NonGradient::printSimplex( std::vector< double >& p_simplex, std::vector< double >& p_height )
     249                 :            : {
     250                 :          0 :     int numRow = getDimension();
     251                 :          0 :     int numCol = numRow + 1;
     252         [ #  # ]:          0 :     for( int col = 0; col < numCol; col++ )
     253                 :            :     {
     254                 :            :         // std::cout << "simplex[ " << col << "]= " ;
     255         [ #  # ]:          0 :         for( int row = 0; row < numRow; row++ )
     256                 :            :         {
     257                 :          0 :             std::cout << p_simplex[row + col * numRow] << " ";
     258                 :            :         }
     259                 :            :         // std::cout << "           "  << p_height[col] << std::endl;
     260                 :            :     }
     261         [ #  # ]:          0 :     for( int col = 0; col < numCol; col++ )
     262                 :            :     {
     263                 :          0 :         std::cout << p_height[col] << " ";
     264                 :            :     }
     265                 :          0 :     std::cout << std::endl;
     266                 :          0 : }
     267                 :            : 
     268                 :        850 : int NonGradient::getPatchDimension( const PatchData& pd, MsqError& err )
     269                 :            : {
     270                 :        850 :     const size_t numElt = pd.num_elements();
     271                 :        850 :     unsigned edimMax    = 0;  // in case numElt == 0
     272         [ +  + ]:       5850 :     for( size_t elementId = 0; elementId < numElt; elementId++ )
     273                 :            :     {
     274                 :       5000 :         const MsqMeshEntity& element = pd.element_by_index( elementId );
     275                 :       5000 :         EntityTopology type          = element.get_element_type();
     276                 :       5000 :         unsigned edim                = TopologyInfo::dimension( type );
     277         [ +  + ]:       5000 :         if( elementId == 0 ) { edimMax = edim; }
     278                 :            :         else
     279                 :            :         {
     280         [ -  + ]:       4150 :             if( edimMax != edim )
     281                 :            :             {
     282                 :            :                 MSQ_SETERR( err )
     283         [ #  # ]:          0 :                 ( "A patch has elements of different dimensions", MsqError::INVALID_MESH );
     284                 :          0 :                 std::cout << "A patch has elements of different dimensions" << edimMax << "  " << edim << std::endl;
     285         [ #  # ]:          0 :                 if( edimMax < edim ) { edimMax = edim; }
     286                 :            :             }
     287                 :            :         }
     288                 :            :     }
     289                 :        850 :     return ( edimMax );
     290                 :            : }
     291                 :            : 
     292                 :          5 : void NonGradient::initialize( PatchData& /*pd*/, MsqError& /*err*/ ) {}
     293                 :            : 
     294                 :        850 : void NonGradient::initialize_mesh_iteration( PatchData& pd, MsqError& err )
     295                 :            : {
     296         [ +  - ]:        850 :     unsigned elementDimension = getPatchDimension( pd, err );  // to do: react to error
     297         [ +  - ]:        850 :     unsigned dimension        = elementDimension * pd.num_free_vertices();
     298                 :            :     // printPatch( pd, err );
     299         [ +  - ]:        850 :     setDimension( dimension );
     300                 :        850 :     int maxNumEval = 100 * dimension;  // 1. Make this a user parameter
     301         [ +  - ]:        850 :     setMaxNumEval( maxNumEval );
     302                 :        850 :     double threshold = 1.e-10;  // avoid division by zero
     303         [ +  - ]:        850 :     setThreshold( threshold );
     304                 :        850 :     double minEdgeLen = 0.0;
     305                 :        850 :     double maxEdgeLen = 0.0;
     306                 :            :     //  double ftol = 0.;
     307         [ +  - ]:        850 :     if( dimension > 0 )
     308                 :            :     {
     309         [ +  - ]:        850 :         pd.get_minmax_edge_length( minEdgeLen, maxEdgeLen );
     310                 :            :         // ftol = minEdgeLen * 1.e-4; // Turn off Amoeba convergence criterion
     311         [ -  + ]:        850 :         if( mNonGradDebug >= 1 )
     312 [ #  # ][ #  # ]:          0 :         { std::cout << "minimum edge length " << minEdgeLen << " maximum edge length " << maxEdgeLen << std::endl; }
         [ #  # ][ #  # ]
                 [ #  # ]
     313                 :            :         MSQ_PRINT( 3 )
     314                 :            :         ( "minimum edge length %e    maximum edge length %e\n", minEdgeLen, maxEdgeLen );
     315                 :            :     }
     316                 :            :     //  setTolerance(ftol);
     317                 :        850 :     unsigned numRow = dimension;
     318                 :        850 :     unsigned numCol = numRow + 1;
     319         [ +  - ]:        850 :     if( numRow * numCol <= simplex.max_size() )
     320                 :            :     {
     321         [ +  - ]:        850 :         simplex.assign( numRow * numCol, 0. );  // guard against previous simplex value
     322                 :        850 :         double scale = minEdgeLen * mScaleDiameter;
     323                 :            :         ;
     324         [ +  - ]:        850 :         const MsqVertex* coord = pd.get_vertex_array( err );
     325 [ +  - ][ -  + ]:        850 :         if( pd.num_free_vertices() > 1 )
     326                 :            :         {
     327                 :            :             MSQ_SETERR( err )
     328 [ #  # ][ #  # ]:          0 :             ( "Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED );
     329                 :            :         }
     330                 :        850 :         size_t index = 0;
     331         [ +  + ]:       3400 :         for( unsigned col = 0; col < numCol; col++ )
     332                 :            :         {
     333         [ +  + ]:       7650 :             for( unsigned row = 0; row < numRow; row++ )
     334                 :            :             {
     335 [ +  - ][ +  - ]:       5100 :                 simplex[row + col * numRow] = coord[index][row];
     336 [ +  + ][ +  - ]:       5100 :                 if( row == col - 1 ) { simplex[row + col * numRow] += scale / static_cast< double >( numCol ); }
     337                 :            :             }
     338                 :            :         }
     339                 :            :     }
     340                 :            :     else
     341                 :            :     {
     342 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "Use patch with fewer free vertices", MsqError::OUT_OF_MEMORY );
     343 [ #  # ][ #  # ]:          0 :         if( mNonGradDebug >= 1 ) { std::cout << "ERROR: Too many free vertices in patch" << std::endl; }
                 [ #  # ]
     344                 :            :         // MSQ_PRINT(1)("ERROR: Too many free vertices in patch\n");
     345                 :            :     }
     346                 :        850 : }
     347                 :            : 
     348                 :        850 : void NonGradient::optimize_vertex_positions( PatchData& pd, MsqError& err )
     349                 :            : {
     350                 :            :     MSQ_FUNCTION_TIMER( "NonGradient::optimize_vertex_positions" );
     351         [ +  - ]:        850 :     int numRow = getDimension();
     352                 :        850 :     int numCol = numRow + 1;
     353         [ +  - ]:        850 :     std::vector< double > p_height( numCol );
     354                 :            : 
     355         [ +  + ]:       3400 :     for( int col = 0; col < numCol; col++ )
     356                 :            :     {
     357 [ +  - ][ +  - ]:       2550 :         p_height[col] = evaluate( &simplex[col * numRow], pd, err );  //  eval patch stuff
                 [ +  - ]
     358                 :            :     }
     359 [ -  + ][ #  # ]:        850 :     if( mNonGradDebug > 0 ) { printSimplex( simplex, p_height ); }
     360                 :            : 
     361                 :            :     // standardization
     362         [ +  - ]:        850 :     TerminationCriterion* term_crit = get_inner_termination_criterion();
     363                 :            :     // int maxNumEval = getMaxNumEval();
     364                 :            :     // double threshold = getThreshold();
     365                 :            : 
     366                 :            :     //  double ftol = getTolerance();
     367                 :        850 :     int ilo  = 0;  // height[ilo]<=...
     368                 :        850 :     int inhi = 0;  //...<=height[inhi]<=
     369                 :        850 :     int ihi  = 0;  //<=height[ihi]
     370                 :            :     //  double rtol = 2.*ftol;
     371                 :            :     double ysave;
     372                 :            :     double ytry;
     373                 :        850 :     bool afterEvaluation = false;
     374         [ +  - ]:       1700 :     std::vector< double > rowSum( numRow );
     375         [ +  - ]:        850 :     getRowSum( numRow, numCol, simplex, rowSum );
     376 [ +  - ][ +  + ]:       9536 :     while( !( term_crit->terminate() ) )
     377                 :            :     {
     378                 :            : 
     379 [ -  + ][ #  # ]:       8686 :         if( mNonGradDebug > 0 ) { printSimplex( simplex, p_height ); }
     380                 :            :         // std::cout << "rtol " << rtol << " ftol " << ftol << " MesquiteIter " <<
     381                 :            :         // term_crit->get_iteration_count() << " Done " << term_crit->terminate() << std::endl;
     382                 :            : 
     383         [ +  + ]:       8686 :         if( afterEvaluation )
     384                 :            :         {
     385                 :            :             // reflect highPt through opposite face
     386                 :            :             // p_height[0] may vanish
     387                 :            :             /*
     388                 :            :                   if( !testRowSum( numRow, numCol, &simplex[0], &rowSum[0]) )
     389                 :            :                   {
     390                 :            :                     // Before uncommenting here and ...
     391                 :            :                     //MSQ_SETERR(err)("Internal check sum test A failed", MsqError::INTERNAL_ERROR);
     392                 :            :                     //MSQ_ERRRTN(err);
     393                 :            :                   }
     394                 :            :             */
     395 [ +  - ][ +  - ]:       7836 :             ytry = amotry( simplex, p_height, &rowSum[0], ihi, -1.0, pd, err );
     396                 :            :             /*
     397                 :            :                   if( !testRowSum( numRow, numCol, &simplex[0], &rowSum[0]) )
     398                 :            :                   {
     399                 :            :                      // ... here, determine a maxVal majorizing the previous as well as the current
     400                 :            :                simplex.
     401                 :            :                      //MSQ_SETERR(err)("Internal check sum test B failed",
     402                 :            :                MsqError::INTERNAL_ERROR);
     403                 :            :                      //MSQ_ERRRTN(err);
     404                 :            :                   }
     405                 :            :             */
     406                 :            : 
     407                 :            :             /*
     408                 :            :                   if( p_height[0] == 0.)
     409                 :            :                   {
     410                 :            :                      MSQ_SETERR(err)("(B) Zero objective function value", MsqError::INTERNAL_ERROR);
     411                 :            :                      exit(-1);
     412                 :            :                   }
     413                 :            :             */
     414 [ +  - ][ +  + ]:       7836 :             if( ytry <= p_height[ilo] )
     415                 :            :             {
     416 [ +  - ][ +  - ]:       4542 :                 ytry = amotry( simplex, p_height, &rowSum[0], ihi, -2.0, pd, err );
     417 [ -  + ][ #  # ]:       4542 :                 if( mNonGradDebug >= 3 ) { std::cout << "Reflect and Expand from highPt " << ytry << std::endl; }
         [ #  # ][ #  # ]
     418                 :            :                 // MSQ_PRINT(3)("Reflect and Expand from highPt : %e\n",ytry);
     419                 :            :             }
     420                 :            :             else
     421                 :            :             {
     422 [ +  - ][ +  + ]:       3294 :                 if( ytry >= p_height[inhi] )
     423                 :            :                 {
     424         [ +  - ]:       2916 :                     ysave = p_height[ihi];  // Contract along highPt
     425 [ +  - ][ +  - ]:       2916 :                     ytry  = amotry( simplex, p_height, &rowSum[0], ihi, 0.5, pd, err );
     426         [ +  + ]:       2916 :                     if( ytry >= ysave )
     427                 :            :                     {  // contract all directions toward lowPt
     428         [ +  + ]:      10860 :                         for( int col = 0; col < numCol; col++ )
     429                 :            :                         {
     430         [ +  + ]:       3024 :                             if( col != ilo )
     431                 :            :                             {
     432         [ +  + ]:       6048 :                                 for( int row = 0; row < numRow; row++ )
     433                 :            :                                 {
     434 [ +  - ][ +  - ]:       4032 :                                     rowSum[row] = 0.5 * ( simplex[row + col * numRow] + simplex[row + ilo * numRow] );
                 [ +  - ]
     435 [ +  - ][ +  - ]:       4032 :                                     simplex[row + col * numRow] = rowSum[row];
     436                 :            :                                 }
     437 [ +  - ][ +  - ]:       2016 :                                 p_height[col] = evaluate( &rowSum[0], pd, err );
                 [ +  - ]
     438         [ -  + ]:       2016 :                                 if( mNonGradDebug >= 3 )
     439                 :            :                                 {
     440 [ #  # ][ #  # ]:          0 :                                     std::cout << "Contract all directions toward lowPt value( " << col
     441 [ #  # ][ #  # ]:       2016 :                                               << " ) = " << p_height[col] << " ilo = " << ilo << std::endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     442                 :            :                                 }
     443                 :            :                                 // MSQ_PRINT(3)("Contract all directions toward lowPt value( %d ) =
     444                 :            :                                 // %e    ilo = %d\n", col, p_height[col], ilo);
     445                 :            :                             }
     446                 :            :                         }
     447                 :            :                     }
     448                 :            :                 }
     449                 :            :             }     // ytri > h(ilo)
     450                 :            :         }         // after evaluation
     451                 :       8686 :         ilo = 1;  // conditional operator or inline if
     452 [ +  - ][ +  - ]:       8686 :         ihi = p_height[0] > p_height[1] ? ( inhi = 1, 0 ) : ( inhi = 0, 1 );
                 [ +  + ]
     453         [ +  + ]:      34744 :         for( int col = 0; col < numCol; col++ )
     454                 :            :         {
     455 [ +  - ][ +  - ]:      26058 :             if( p_height[col] <= p_height[ilo] )
                 [ +  + ]
     456                 :            :             {
     457                 :      21035 :                 ilo = col;  // ilo := argmin height
     458                 :            :             }
     459 [ +  - ][ +  - ]:      26058 :             if( p_height[col] > p_height[ihi] )
                 [ +  + ]
     460                 :            :             {
     461                 :       1169 :                 inhi = ihi;
     462                 :       1169 :                 ihi  = col;
     463                 :            :             }
     464                 :            :             else  // p_height[ihi] >= p_height[col]
     465 [ +  + ][ +  - ]:      24889 :                 if( col != ihi && p_height[col] > p_height[inhi] )
         [ +  - ][ +  + ]
                 [ +  + ]
     466                 :       1109 :                 inhi = col;
     467                 :            :         }
     468                 :            :         //    rtol=2.0*fabs( p_height[ihi]-p_height[ilo] )/
     469                 :            :         //         ( fabs(p_height[ihi])+fabs(p_height[ilo])+threshold );
     470                 :       8686 :         afterEvaluation = true;
     471                 :            :     }  //  while not converged
     472                 :            : 
     473                 :            :     // Always set to current best mesh.
     474                 :            :     {
     475         [ +  + ]:        850 :         if( ilo != 0 )
     476                 :            :         {
     477         [ +  - ]:        778 :             double yTemp  = p_height[0];
     478 [ +  - ][ +  - ]:        778 :             p_height[0]   = p_height[ilo];  // height dimension numCol
     479         [ +  - ]:        778 :             p_height[ilo] = yTemp;
     480         [ +  + ]:       1556 :             for( int row = 1; row < numRow; row++ )
     481                 :            :             {
     482         [ +  - ]:        778 :                 yTemp                       = simplex[row];
     483 [ +  - ][ +  - ]:        778 :                 simplex[row]                = simplex[row + ilo * numRow];
     484         [ +  - ]:        778 :                 simplex[row + ilo * numRow] = yTemp;
     485                 :            :             }
     486                 :            :         }
     487                 :            :     }
     488 [ +  - ][ -  + ]:        850 :     if( pd.num_free_vertices() > 1 )
     489                 :            :     {
     490                 :            :         MSQ_SETERR( err )
     491 [ #  # ][ #  # ]:          0 :         ( "Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED );
     492                 :            :     }
     493                 :            : 
     494 [ +  - ][ +  - ]:        850 :     Vector3D newPoint( &simplex[0] );
     495                 :        850 :     size_t vertexIndex = 0;  // fix c.f. freeVertexIndex
     496         [ +  - ]:        850 :     pd.set_vertex_coordinates( newPoint, vertexIndex, err );
     497         [ +  - ]:        850 :     pd.snap_vertex_to_domain( vertexIndex, err );
     498 [ +  - ][ +  - ]:        850 :     if( term_crit->terminate() )
     499                 :            :     {
     500 [ -  + ][ #  # ]:        850 :         if( mNonGradDebug >= 1 ) { std::cout << "Optimization Termination OptStatus: Max Iter Exceeded" << std::endl; }
                 [ #  # ]
     501                 :            :         // MSQ_PRINT(1)("Optimization Termination OptStatus: Max Iter Exceeded\n");
     502                 :        850 :     }
     503                 :        850 : }
     504                 :            : 
     505                 :         50 : void NonGradient::terminate_mesh_iteration( PatchData& /*pd*/, MsqError& /*err*/ )
     506                 :            : {
     507         [ -  + ]:         50 :     if( mNonGradDebug >= 2 ) { std::cout << "- Executing NonGradient::iteration_complete()" << std::endl; }
     508                 :            :     // MSQ_PRINT(2)("\n - Executing NonGradient::iteration_complete() \n");
     509                 :         50 : }
     510                 :            : 
     511                 :          2 : void NonGradient::cleanup()
     512                 :            : {
     513         [ -  + ]:          2 :     if( mNonGradDebug >= 2 ) { std::cout << " - Executing NonGradient::iteration_end()" << std::endl; }
     514                 :            :     // MSQ_PRINT(2)("\n - Executing NonGradient::iteration_end() \n");
     515                 :          2 : }
     516                 :            : 
     517 [ +  - ][ +  - ]:        120 : }  // namespace MBMesquite

Generated by: LCOV version 1.11