LCOV - code coverage report
Current view: top level - src/mesquite/QualityImprover - VertexMover.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 199 479 41.5 %
Date: 2020-07-18 00:09:26 Functions: 8 12 66.7 %
Branches: 320 1649 19.4 %

           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   VertexMover.cpp
      29                 :            :   \brief
      30                 :            : 
      31                 :            :   The VertexMover Class is the base class for all the smoothing algorythms
      32                 :            : 
      33                 :            :   \author Thomas Leurent
      34                 :            :   \date   2002-01-17
      35                 :            : */
      36                 :            : 
      37                 :            : #include "VertexMover.hpp"
      38                 :            : #include "NonGradient.hpp"
      39                 :            : #include "QualityMetric.hpp"
      40                 :            : #include "TQualityMetric.hpp"
      41                 :            : #include "TMetricBarrier.hpp"
      42                 :            : #include "AWMetricBarrier.hpp"
      43                 :            : #include "ElementMaxQM.hpp"
      44                 :            : #include "ElementAvgQM.hpp"
      45                 :            : #include "ElementPMeanP.hpp"
      46                 :            : #include "PlanarDomain.hpp"
      47                 :            : #include "ObjectiveFunctionTemplate.hpp"
      48                 :            : #include "MaxTemplate.hpp"
      49                 :            : #include "MsqTimer.hpp"
      50                 :            : #include "MsqDebug.hpp"
      51                 :            : #include "PatchSet.hpp"
      52                 :            : #include "PatchData.hpp"
      53                 :            : #include "ParallelHelperInterface.hpp"
      54                 :            : #include <algorithm>
      55                 :            : 
      56                 :            : namespace MBMesquite
      57                 :            : {
      58                 :            : 
      59                 :            : extern int get_parallel_rank();
      60                 :            : extern int get_parallel_size();
      61                 :            : extern void parallel_barrier();
      62                 :            : 
      63         [ +  - ]:        163 : VertexMover::VertexMover( ObjectiveFunction* OF ) : QualityImprover(), objFuncEval( OF ), jacobiOpt( false ) {}
      64                 :            : 
      65         [ -  + ]:        312 : VertexMover::~VertexMover() {}
      66                 :            : 
      67                 :            : /*
      68                 :            : 
      69                 :            :     +-----------+
      70                 :            :     |Reset Outer|
      71                 :            :     |Criterion  |
      72                 :            :     +-----------+
      73                 :            :           |
      74                 :            :           V
      75                 :            :           +
      76                 :            :         /   \
      77                 :            :        /Outer\  YES
      78                 :            : +--> <Criterion>-----> DONE
      79                 :            : |      \Done?/
      80                 :            : |       \   /
      81                 :            : |         +
      82                 :            : |         |NO
      83                 :            : |         V
      84                 :            : |   +-----------+
      85                 :            : 1   |Reset Mesh |
      86                 :            : |   | Iteration |
      87                 :            : |   +-----------+
      88                 :            : |         |
      89                 :            : |         V
      90                 :            : |         +
      91                 :            : |       /  \
      92                 :            : |   NO /Next\
      93                 :            : +-----<Patch > <-----+
      94                 :            :        \    /        |
      95                 :            :         \  /         |
      96                 :            :           +          |
      97                 :            :        YES|          |
      98                 :            :           V          |
      99                 :            :     +-----------+    |
     100                 :            :     |Reset Inner|    |
     101                 :            :     |Criterion  |    2
     102                 :            :     +-----------+    |
     103                 :            :           |          |
     104                 :            :           V          |
     105                 :            :           +          |
     106                 :            :         /   \        |
     107                 :            :        /Inner\  YES  |
     108                 :            : +--> <Criterion>-----+    --------------+
     109                 :            : |      \Done?/                          |
     110                 :            : |       \   /                           |
     111                 :            : |         +                             |
     112                 :            : |         |NO                           |
     113                 :            : |         V                          Inside
     114                 :            : 3   +-----------+                    Smoother
     115                 :            : |   |   Smooth  |                       |
     116                 :            : |   |   Patch   |                       |
     117                 :            : |   +-----------+                       |
     118                 :            : |         |                             |
     119                 :            : ----------+               --------------+
     120                 :            : 
     121                 :            : */
     122                 :            : 
     123                 :            : /*! \brief Improves the quality of the MeshSet, calling some
     124                 :            :     methods specified in a class derived from VertexMover
     125                 :            : 
     126                 :            :     \param const MeshSet &: this MeshSet is looped over. Only the
     127                 :            :     mutable data members are changed (such as currentVertexInd).
     128                 :            :   */
     129                 :        130 : double VertexMover::loop_over_mesh( MeshDomainAssoc* mesh_and_domain, const Settings* settings, MsqError& err )
     130                 :            : {
     131         [ +  - ]:        130 :     Mesh* mesh         = mesh_and_domain->get_mesh();
     132         [ +  - ]:        130 :     MeshDomain* domain = mesh_and_domain->get_domain();
     133                 :            : 
     134                 :        130 :     TagHandle coord_tag      = 0;  // store uncommitted coords for jacobi optimization
     135                 :        130 :     TagHandle* coord_tag_ptr = 0;
     136                 :            : 
     137                 :        130 :     TerminationCriterion* outer_crit = 0;
     138                 :        130 :     TerminationCriterion* inner_crit = 0;
     139                 :            : 
     140                 :            :     // Clear culling flag, set hard fixed flag, etc on all vertices
     141         [ +  - ]:        130 :     initialize_vertex_byte( mesh_and_domain, settings, err );
     142 [ +  - ][ -  + ]:        130 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     143                 :            : 
     144                 :            :     // Get the patch data to use for the first iteration
     145         [ +  - ]:        130 :     OFEvaluator& obj_func = get_objective_function_evaluator();
     146                 :            : 
     147                 :            :     // Check for impromer use of MaxTemplate
     148 [ +  - ][ +  + ]:        130 :     ObjectiveFunctionTemplate* maxt_ptr = dynamic_cast< MaxTemplate* >( obj_func.get_objective_function() );
     149         [ +  + ]:        130 :     if( maxt_ptr )
     150                 :            :     {
     151         [ -  + ]:          2 :         QualityImprover* ngqi_ptr = dynamic_cast< NonGradient* >( this );
     152         [ -  + ]:          2 :         if( !ngqi_ptr )
     153 [ #  # ][ #  # ]:          0 :             std::cout << "Warning: MaxTemplate results in non-differentiable objective function." << std::endl
     154 [ #  # ][ #  # ]:          0 :                       << "   Therefore, it is best to use the NonGradient solver. Other Mesquite" << std::endl
     155 [ #  # ][ #  # ]:          2 :                       << "   solvers require derivative information." << std::endl;
     156                 :            :     }
     157                 :            : 
     158         [ +  - ]:        130 :     PatchData patch;
     159         [ +  - ]:        130 :     patch.set_mesh( mesh );
     160         [ +  - ]:        130 :     patch.set_domain( domain );
     161 [ +  - ][ +  - ]:        130 :     if( settings ) patch.attach_settings( settings );
     162                 :        130 :     bool one_patch = false, inner_crit_terminated, all_culled;
     163         [ +  - ]:        260 :     std::vector< Mesh::VertexHandle > patch_vertices;
     164         [ +  - ]:        260 :     std::vector< Mesh::ElementHandle > patch_elements;
     165                 :            :     bool valid;
     166                 :            : 
     167         [ +  - ]:        130 :     PatchSet* patch_set = get_patch_set();
     168         [ -  + ]:        130 :     if( !patch_set )
     169                 :            :     {
     170 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "No PatchSet for QualityImprover!", MsqError::INVALID_STATE );
     171                 :          0 :         return 0.0;
     172                 :            :     }
     173         [ +  - ]:        130 :     patch_set->set_mesh( mesh );
     174                 :            : 
     175         [ +  - ]:        260 :     std::vector< PatchSet::PatchHandle > patch_list;
     176         [ +  - ]:        130 :     patch_set->get_patch_handles( patch_list, err );
     177 [ +  - ][ -  + ]:        130 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     178                 :            : 
     179                 :            :     // check for inverted elements when using a barrietr target metric
     180                 :        130 :     TQualityMetric* tqm_ptr        = NULL;
     181                 :        130 :     TMetricBarrier* tm_ptr         = NULL;
     182                 :        130 :     AWMetricBarrier* awm_ptr       = NULL;
     183                 :        130 :     ElemSampleQM* sample_qm_ptr    = NULL;
     184                 :        130 :     QualityMetric* qm_ptr          = NULL;
     185                 :        130 :     TQualityMetric* pmeanp_ptr     = NULL;
     186                 :        130 :     ElementMaxQM* elem_max_ptr     = NULL;
     187                 :        130 :     ElementAvgQM* elem_avg_ptr     = NULL;
     188                 :        130 :     ElementPMeanP* elem_pmeanp_ptr = NULL;
     189                 :            : 
     190 [ +  - ][ +  + ]:        130 :     ObjectiveFunctionTemplate* of_ptr = dynamic_cast< ObjectiveFunctionTemplate* >( obj_func.get_objective_function() );
     191 [ +  + ][ +  - ]:        130 :     if( of_ptr ) qm_ptr = of_ptr->get_quality_metric();
     192         [ +  + ]:        130 :     if( qm_ptr )
     193                 :            :     {
     194         [ -  + ]:        123 :         pmeanp_ptr      = dynamic_cast< TQualityMetric* >( qm_ptr );  // PMeanP case
     195         [ -  + ]:        123 :         elem_max_ptr    = dynamic_cast< ElementMaxQM* >( qm_ptr );
     196         [ -  + ]:        123 :         elem_avg_ptr    = dynamic_cast< ElementAvgQM* >( qm_ptr );
     197         [ -  + ]:        123 :         elem_pmeanp_ptr = dynamic_cast< ElementPMeanP* >( qm_ptr );
     198                 :            :     }
     199         [ +  + ]:        130 :     if( elem_max_ptr )
     200         [ +  - ]:          2 :         sample_qm_ptr = elem_max_ptr->get_quality_metric();
     201         [ +  + ]:        128 :     else if( elem_pmeanp_ptr )
     202         [ +  - ]:         34 :         sample_qm_ptr = elem_pmeanp_ptr->get_quality_metric();
     203         [ -  + ]:         94 :     else if( elem_avg_ptr )
     204         [ #  # ]:          0 :         sample_qm_ptr = elem_avg_ptr->get_quality_metric();
     205         [ +  + ]:         94 :     else if( pmeanp_ptr )
     206                 :            :     {
     207 [ +  - ][ -  + ]:         45 :         tm_ptr  = dynamic_cast< TMetricBarrier* >( pmeanp_ptr->get_target_metric() );
     208 [ +  - ][ -  + ]:         45 :         awm_ptr = dynamic_cast< AWMetricBarrier* >( pmeanp_ptr->get_target_metric() );
     209                 :            :     }
     210                 :            : 
     211 [ +  + ][ +  + ]:        130 :     if( sample_qm_ptr || pmeanp_ptr )
     212                 :            :     {
     213         [ +  + ]:         81 :         if( !pmeanp_ptr )
     214                 :            :         {
     215         [ -  + ]:         36 :             tqm_ptr = dynamic_cast< TQualityMetric* >( sample_qm_ptr );
     216         [ +  + ]:         36 :             if( tqm_ptr )
     217                 :            :             {
     218 [ +  - ][ -  + ]:         35 :                 tm_ptr  = dynamic_cast< TMetricBarrier* >( tqm_ptr->get_target_metric() );
     219 [ +  - ][ -  + ]:         35 :                 awm_ptr = dynamic_cast< AWMetricBarrier* >( tqm_ptr->get_target_metric() );
     220                 :            :             }
     221                 :            :         }
     222                 :            :         else
     223                 :            :         {
     224                 :         45 :             tqm_ptr = dynamic_cast< TQualityMetric* >( pmeanp_ptr );
     225                 :            :         }
     226                 :            : 
     227 [ +  + ][ +  + ]:         81 :         if( tqm_ptr && ( tm_ptr || awm_ptr ) )
                 [ -  + ]
     228                 :            :         {
     229                 :            :             // check for inverted elements
     230         [ +  - ]:         31 :             this->initialize( patch, err );
     231         [ +  - ]:         31 :             std::vector< size_t > handles;
     232                 :            : 
     233                 :            :             // set up patch data
     234                 :         31 :             std::vector< PatchSet::PatchHandle >::iterator patch_iter = patch_list.begin();
     235 [ +  - ][ +  + ]:         92 :             while( patch_iter != patch_list.end() )
              [ +  -  + ]
     236                 :            :             {
     237         [ -  + ]:         61 :                 do
     238                 :            :                 {
     239 [ +  - ][ +  - ]:         61 :                     patch_set->get_patch( *patch_iter, patch_elements, patch_vertices, err );
     240 [ +  - ][ -  + ]:         61 :                     if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     241         [ +  - ]:         61 :                     ++patch_iter;
     242 [ -  + ][ #  # ]:         61 :                 } while( patch_elements.empty() && patch_iter != patch_list.end() );
         [ #  # ][ +  - ]
                 [ #  # ]
     243                 :            : 
     244         [ +  - ]:         61 :                 patch.set_mesh_entities( patch_elements, patch_vertices, err );
     245 [ +  - ][ -  + ]:         61 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     246                 :            : 
     247         [ +  - ]:         61 :                 qm_ptr->get_evaluations( patch, handles, true, err );  // MSQ_ERRFALSE(err);
     248                 :            : 
     249                 :            :                 // do actual check for inverted elements
     250                 :         61 :                 std::vector< size_t >::const_iterator i;
     251                 :            :                 double tvalue;
     252 [ +  - ][ +  - ]:      33783 :                 for( i = handles.begin(); i != handles.end(); ++i )
         [ +  - ][ +  + ]
     253                 :            :                 {
     254 [ +  - ][ +  - ]:      33724 :                     bool result = tqm_ptr->evaluate( patch, *i, tvalue, err );
     255 [ +  - ][ +  + ]:      33724 :                     if( MSQ_CHKERR( err ) || !result ) return false;  // inverted element detected
         [ +  - ][ -  + ]
         [ -  + ][ +  + ]
     256                 :            :                 }
     257                 :         31 :             }
     258                 :            :         }
     259                 :            :     }
     260                 :            : 
     261                 :            :     // Get termination criteria
     262         [ +  - ]:        128 :     outer_crit = this->get_outer_termination_criterion();
     263         [ +  - ]:        128 :     inner_crit = this->get_inner_termination_criterion();
     264         [ -  + ]:        128 :     if( outer_crit == 0 )
     265                 :            :     {
     266 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "Termination Criterion pointer is Null", MsqError::INVALID_STATE );
     267                 :          0 :         return 0.;
     268                 :            :     }
     269         [ -  + ]:        128 :     if( inner_crit == 0 )
     270                 :            :     {
     271                 :            :         MSQ_SETERR( err )
     272 [ #  # ][ #  # ]:          0 :         ( "Termination Criterion pointer for inner loop is Null", MsqError::INVALID_STATE );
     273                 :          0 :         return 0.;
     274                 :            :     }
     275                 :            : 
     276                 :            :     // Set Termination Criterion defaults if no other Criterion is set
     277 [ +  - ][ +  + ]:        128 :     if( !outer_crit->criterion_is_set() ) outer_crit->add_iteration_limit( 1 );
                 [ +  - ]
     278 [ +  - ][ +  + ]:        128 :     if( !inner_crit->criterion_is_set() ) inner_crit->add_iteration_limit( 10 );
                 [ +  - ]
     279                 :            : 
     280                 :            :     // If using a local patch, suppress output of inner termination criterion
     281         [ +  + ]:        128 :     if( patch_list.size() > 1 )
     282         [ +  - ]:         34 :         inner_crit->set_debug_output_level( 3 );
     283                 :            :     else
     284                 :         94 :         one_patch = true;
     285                 :            : 
     286         [ +  + ]:        128 :     if( jacobiOpt )
     287                 :            :     {
     288         [ +  - ]:          1 :         coord_tag = get_jacobi_coord_tag( mesh, err );
     289 [ +  - ][ -  + ]:          1 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
     290                 :          1 :         coord_tag_ptr = &coord_tag;
     291                 :            :     }
     292                 :            : 
     293                 :            :     // Initialize outer loop
     294                 :            : 
     295         [ +  - ]:        128 :     this->initialize( patch, err );
     296 [ +  - ][ -  + ]:        128 :     if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     297                 :            : 
     298         [ +  - ]:        128 :     valid = obj_func.initialize( mesh_and_domain, settings, patch_set, err );
     299 [ +  - ][ -  + ]:        128 :     if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     300         [ -  + ]:        128 :     if( !valid )
     301                 :            :     {
     302                 :            :         MSQ_SETERR( err )
     303                 :            :         ( "ObjectiveFunction initialization failed.  Mesh "
     304                 :            :           "invalid at one or more sample points.",
     305 [ #  # ][ #  # ]:          0 :           MsqError::INVALID_MESH );
     306                 :          0 :         goto ERROR;
     307                 :            :     }
     308                 :            : 
     309         [ +  - ]:        128 :     outer_crit->reset_outer( mesh, domain, obj_func, settings, err );
     310 [ +  - ][ -  + ]:        128 :     if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     311                 :            : 
     312                 :            :     // if only one patch, get the patch now
     313         [ +  + ]:        128 :     if( one_patch )
     314                 :            :     {
     315 [ +  - ][ +  - ]:         94 :         patch_set->get_patch( patch_list[0], patch_elements, patch_vertices, err );
     316 [ +  - ][ -  + ]:         94 :         if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     317         [ +  - ]:         94 :         patch.set_mesh_entities( patch_elements, patch_vertices, err );
     318 [ +  - ][ -  + ]:         94 :         if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     319                 :            :     }
     320                 :            : 
     321                 :            :     // Loop until outer termination criterion is met
     322                 :        128 :     inner_crit_terminated = false;
     323 [ +  - ][ +  + ]:        957 :     while( !outer_crit->terminate() )
     324                 :            :     {
     325         [ -  + ]:        832 :         if( inner_crit_terminated )
     326                 :            :         {
     327                 :            :             MSQ_SETERR( err )
     328                 :            :             ( "Inner termiation criterion satisfied for all patches "
     329                 :            :               "without meeting outer termination criterion.  This is "
     330                 :            :               "an infinite loop.  Aborting.",
     331 [ #  # ][ #  # ]:          0 :               MsqError::INVALID_STATE );
     332                 :          3 :             break;
     333                 :            :         }
     334                 :        832 :         inner_crit_terminated = true;
     335                 :        832 :         all_culled            = true;
     336                 :            : 
     337                 :        832 :         int num_patches = 0;
     338                 :            :         // Loop over each patch
     339                 :        832 :         std::vector< PatchSet::PatchHandle >::iterator p_iter = patch_list.begin();
     340 [ +  - ][ +  + ]:     830780 :         while( p_iter != patch_list.end() )
     341                 :            :         {
     342         [ +  + ]:     830141 :             if( !one_patch )
     343                 :            :             {  // if only one patch (global) re-use the previous one
     344                 :            :                 // loop until we get a non-empty patch.  patch will be empty
     345                 :            :                 // for culled vertices with element-on-vertex patches
     346         [ +  + ]:     951183 :                 do
     347                 :            :                 {
     348 [ +  - ][ +  - ]:     890463 :                     patch_set->get_patch( *p_iter, patch_elements, patch_vertices, err );
     349 [ +  - ][ -  + ]:     890463 :                     if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     350         [ +  - ]:     890463 :                     ++p_iter;
     351 [ +  + ][ +  - ]:     951183 :                 } while( patch_elements.empty() && p_iter != patch_list.end() );
         [ +  + ][ +  + ]
                 [ #  # ]
     352                 :            : 
     353         [ +  + ]:     829936 :                 if( patch_elements.empty() )
     354                 :            :                 {  // no more non-culled vertices
     355                 :            :                     if( 0 ) std::cout << "P[" << get_parallel_rank() << "] tmp srk all vertices culled." << std::endl;
     356                 :        193 :                     break;
     357                 :            :                 }
     358                 :            : 
     359                 :     829743 :                 all_culled = false;
     360         [ +  - ]:     829743 :                 patch.set_mesh_entities( patch_elements, patch_vertices, err );
     361 [ +  - ][ -  + ]:     829743 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     362                 :            :             }
     363                 :            :             else
     364                 :            :             {
     365         [ +  - ]:        205 :                 ++p_iter;
     366                 :        205 :                 all_culled = false;
     367                 :            :             }
     368                 :            : 
     369                 :     829948 :             ++num_patches;
     370                 :            : 
     371                 :            :             // Initialize for inner iteration
     372                 :            : 
     373         [ +  - ]:     829948 :             this->initialize_mesh_iteration( patch, err );
     374 [ +  - ][ -  + ]:     829948 :             if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     375                 :            : 
     376         [ +  - ]:     829948 :             obj_func.reset();
     377                 :            : 
     378         [ +  - ]:     829948 :             outer_crit->reset_patch( patch, err );
     379 [ +  - ][ -  + ]:     829948 :             if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     380                 :            : 
     381         [ +  - ]:     829948 :             inner_crit->reset_inner( patch, obj_func, err );
     382 [ +  - ][ -  + ]:     829948 :             if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     383                 :            : 
     384         [ +  - ]:     829948 :             inner_crit->reset_patch( patch, err );
     385 [ +  - ][ -  + ]:     829948 :             if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     386                 :            : 
     387                 :            :             // Don't even call optimizer if inner termination
     388                 :            :             // criterion has already been met.
     389 [ +  - ][ +  + ]:     829948 :             if( !inner_crit->terminate() )
     390                 :            :             {
     391                 :     829946 :                 inner_crit_terminated = false;
     392                 :            : 
     393                 :            :                 // Call optimizer - should loop on inner_crit->terminate()
     394         [ +  - ]:     829946 :                 this->optimize_vertex_positions( patch, err );
     395 [ +  - ][ -  + ]:     829946 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     396                 :            : 
     397                 :            :                 // Update for changes during inner iteration
     398                 :            :                 // (during optimizer loop)
     399                 :            : 
     400         [ +  - ]:     829946 :                 outer_crit->accumulate_patch( patch, err );
     401 [ +  - ][ -  + ]:     829946 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     402                 :            : 
     403         [ +  - ]:     829946 :                 inner_crit->cull_vertices( patch, obj_func, err );
     404 [ +  - ][ -  + ]:     829946 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     405                 :            : 
     406                 :            :                 // FIXME
     407                 :            :                 if( 0 )
     408                 :            :                 {
     409                 :            :                     inner_crit->cull_vertices_global( patch, mesh, domain, settings, obj_func, err );
     410                 :            :                     if( MSQ_CHKERR( err ) ) goto ERROR;
     411                 :            :                 }
     412                 :            : 
     413         [ +  - ]:     829946 :                 patch.update_mesh( err, coord_tag_ptr );
     414 [ +  - ][ -  + ]:     829946 :                 if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     415                 :            :             }
     416                 :            :         }
     417                 :            : 
     418 [ +  + ][ +  - ]:        832 :         if( jacobiOpt ) commit_jacobi_coords( coord_tag, mesh, err );
     419                 :            : 
     420         [ +  - ]:        832 :         this->terminate_mesh_iteration( patch, err );
     421 [ +  - ][ -  + ]:        832 :         if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     422                 :            : 
     423         [ +  - ]:        832 :         outer_crit->accumulate_outer( mesh, domain, obj_func, settings, err );
     424 [ +  - ][ -  + ]:        832 :         if( MSQ_CHKERR( err ) ) goto ERROR;
         [ #  # ][ #  # ]
                 [ -  + ]
     425                 :            : 
     426         [ +  + ]:        832 :         if( all_culled ) break;
     427                 :            :     }
     428                 :            : 
     429                 :            : ERROR:
     430 [ +  + ][ +  - ]:        128 :     if( jacobiOpt ) mesh->tag_delete( coord_tag, err );
     431                 :            : 
     432                 :            :     // call the criteria's cleanup funtions.
     433 [ +  - ][ +  - ]:        128 :     if( outer_crit ) outer_crit->cleanup( mesh, domain, err );
     434 [ +  - ][ +  - ]:        128 :     if( inner_crit ) inner_crit->cleanup( mesh, domain, err );
     435                 :            :     // call the optimization cleanup function.
     436         [ +  - ]:        128 :     this->cleanup();
     437                 :            : 
     438                 :        258 :     return 0.;
     439                 :            : }
     440                 :            : 
     441                 :          0 : static void checkpoint_bytes( Mesh* mesh, std::vector< unsigned char >& saved_bytes, MsqError& err )
     442                 :            : {
     443         [ #  # ]:          0 :     std::vector< Mesh::VertexHandle > vertexHandlesArray;
     444 [ #  # ][ #  # ]:          0 :     mesh->get_all_vertices( vertexHandlesArray, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     445         [ #  # ]:          0 :     saved_bytes.resize( vertexHandlesArray.size() );
     446 [ #  # ][ #  # ]:          0 :     mesh->vertices_get_byte( &vertexHandlesArray[0], &saved_bytes[0], vertexHandlesArray.size(), err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     447                 :            : }
     448                 :            : 
     449                 :          0 : static void restore_bytes( Mesh* mesh, std::vector< unsigned char >& saved_bytes, MsqError& err )
     450                 :            : {
     451         [ #  # ]:          0 :     std::vector< Mesh::VertexHandle > vertexHandlesArray;
     452 [ #  # ][ #  # ]:          0 :     mesh->get_all_vertices( vertexHandlesArray, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     453 [ #  # ][ #  # ]:          0 :     mesh->vertices_set_byte( &vertexHandlesArray[0], &saved_bytes[0], vertexHandlesArray.size(), err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     454                 :            : }
     455                 :            : 
     456                 :          0 : static void save_or_restore_debug_state( bool save )
     457                 :            : {
     458                 :            :     static bool debug[3] = { false, false, false };
     459         [ #  # ]:          0 :     if( save )
     460                 :            :     {
     461                 :          0 :         debug[0] = MsqDebug::get( 1 );
     462                 :          0 :         debug[1] = MsqDebug::get( 2 );
     463                 :          0 :         debug[2] = MsqDebug::get( 3 );
     464                 :            :     }
     465                 :            :     else
     466                 :            :     {
     467         [ #  # ]:          0 :         if( debug[0] ) MsqDebug::enable( 1 );
     468         [ #  # ]:          0 :         if( debug[1] ) MsqDebug::enable( 2 );
     469         [ #  # ]:          0 :         if( debug[2] ) MsqDebug::enable( 3 );
     470                 :            :     }
     471                 :          0 : }
     472                 :            : 
     473                 :            : /*! \brief Improves the quality of the MeshSet, calling some
     474                 :            :     methods specified in a class derived from VertexMover
     475                 :            : 
     476                 :            :     \param const MeshSet &: this MeshSet is looped over. Only the
     477                 :            :     mutable data members are changed (such as currentVertexInd).
     478                 :            :   */
     479                 :          0 : double VertexMover::loop_over_mesh( ParallelMesh* mesh, MeshDomain* domain, const Settings* settings, MsqError& err )
     480                 :            : {
     481         [ #  # ]:          0 :     std::vector< size_t > junk;
     482                 :            :     Mesh::VertexHandle vertex_handle;
     483                 :          0 :     TagHandle coord_tag      = 0;  // store uncommitted coords for jacobi optimization
     484                 :          0 :     TagHandle* coord_tag_ptr = 0;
     485                 :          0 :     int outer_iter           = 0;
     486                 :          0 :     int inner_iter           = 0;
     487                 :          0 :     bool one_patch           = false;
     488                 :            : 
     489                 :            :     // Clear culling flag, set hard fixed flag, etc on all vertices
     490 [ #  # ][ #  # ]:          0 :     MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( (Mesh*)mesh, 0 );
     491         [ #  # ]:          0 :     initialize_vertex_byte( &mesh_and_domain, settings, err );
     492 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     493                 :            : 
     494                 :            :     // Get the patch data to use for the first iteration
     495         [ #  # ]:          0 :     OFEvaluator& obj_func = get_objective_function_evaluator();
     496                 :            : 
     497         [ #  # ]:          0 :     PatchData patch;
     498 [ #  # ][ #  # ]:          0 :     patch.set_mesh( (Mesh*)mesh );
     499         [ #  # ]:          0 :     patch.set_domain( domain );
     500         [ #  # ]:          0 :     patch.attach_settings( settings );
     501                 :            : 
     502         [ #  # ]:          0 :     ParallelHelper* helper = mesh->get_parallel_helper();
     503         [ #  # ]:          0 :     if( !helper )
     504                 :            :     {
     505 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "No ParallelHelper instance", MsqError::INVALID_STATE );
     506                 :          0 :         return 0;
     507                 :            :     }
     508                 :            : 
     509         [ #  # ]:          0 :     helper->smoothing_init( err );
     510 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     511                 :            : 
     512                 :            :     bool inner_crit_terminated, all_culled;
     513         [ #  # ]:          0 :     std::vector< Mesh::VertexHandle > patch_vertices;
     514         [ #  # ]:          0 :     std::vector< Mesh::ElementHandle > patch_elements;
     515         [ #  # ]:          0 :     std::vector< Mesh::VertexHandle > fixed_vertices;
     516         [ #  # ]:          0 :     std::vector< Mesh::VertexHandle > free_vertices;
     517                 :            : 
     518                 :            :     // Get termination criteria
     519         [ #  # ]:          0 :     TerminationCriterion* outer_crit = this->get_outer_termination_criterion();
     520         [ #  # ]:          0 :     TerminationCriterion* inner_crit = this->get_inner_termination_criterion();
     521         [ #  # ]:          0 :     if( outer_crit == 0 )
     522                 :            :     {
     523 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "Termination Criterion pointer is Null", MsqError::INVALID_STATE );
     524                 :          0 :         return 0.;
     525                 :            :     }
     526         [ #  # ]:          0 :     if( inner_crit == 0 )
     527                 :            :     {
     528                 :            :         MSQ_SETERR( err )
     529 [ #  # ][ #  # ]:          0 :         ( "Termination Criterion pointer for inner loop is Null", MsqError::INVALID_STATE );
     530                 :          0 :         return 0.;
     531                 :            :     }
     532                 :            : 
     533         [ #  # ]:          0 :     PatchSet* patch_set = get_patch_set();
     534         [ #  # ]:          0 :     if( !patch_set )
     535                 :            :     {
     536 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "No PatchSet for QualityImprover!", MsqError::INVALID_STATE );
     537                 :          0 :         return 0.0;
     538                 :            :     }
     539 [ #  # ][ #  # ]:          0 :     patch_set->set_mesh( (Mesh*)mesh );
     540                 :            : 
     541         [ #  # ]:          0 :     std::vector< PatchSet::PatchHandle > patch_list;
     542         [ #  # ]:          0 :     patch_set->get_patch_handles( patch_list, err );
     543 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     544                 :            : 
     545         [ #  # ]:          0 :     if( patch_list.size() > 1 )
     546         [ #  # ]:          0 :         inner_crit->set_debug_output_level( 3 );
     547                 :            :     else
     548                 :          0 :         one_patch = true;
     549                 :            : 
     550         [ #  # ]:          0 :     if( jacobiOpt )
     551                 :            :     {
     552 [ #  # ][ #  # ]:          0 :         coord_tag = get_jacobi_coord_tag( mesh, err );
     553 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     554                 :          0 :         coord_tag_ptr = &coord_tag;
     555                 :            :     }
     556                 :            : 
     557                 :            :     // parallel error checking
     558         [ #  # ]:          0 :     MsqError perr;
     559                 :          0 :     bool pdone = false;
     560                 :            : 
     561                 :            : #define PERROR_COND continue
     562                 :            : 
     563                 :            :     // Initialize outer loop
     564                 :            : 
     565         [ #  # ]:          0 :     this->initialize( patch, err );
     566 [ #  # ][ #  # ]:          0 :     if( MSQ_CHKERR( err ) ) { MSQ_SETERR( perr )( "initialize patch", MsqError::INVALID_STATE ); }  // goto ERROR;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     567                 :            : 
     568 [ #  # ][ #  # ]:          0 :     MeshDomainAssoc mesh_and_domain2 = MeshDomainAssoc( (Mesh*)mesh, domain );
     569         [ #  # ]:          0 :     obj_func.initialize( &mesh_and_domain2, settings, patch_set, err );
     570 [ #  # ][ #  # ]:          0 :     if( MSQ_CHKERR( err ) ) { MSQ_SETERR( perr )( "initialize obj_func", MsqError::INVALID_STATE ); }  // goto ERROR;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     571                 :            : 
     572 [ #  # ][ #  # ]:          0 :     outer_crit->reset_outer( (Mesh*)mesh, domain, obj_func, settings, err );
     573 [ #  # ][ #  # ]:          0 :     if( MSQ_CHKERR( err ) ) { MSQ_SETERR( perr )( "reset_outer", MsqError::INVALID_STATE ); }  // goto ERROR;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     574                 :            : 
     575                 :            :     // Loop until outer termination criterion is met
     576                 :          0 :     inner_crit_terminated = false;
     577                 :          0 :     all_culled            = false;
     578                 :            :     for( ;; )
     579                 :            :     {
     580                 :            :         if( 0 )
     581                 :            :             std::cout << "P[" << get_parallel_rank() << "] tmp srk inner_iter= " << inner_iter
     582                 :            :                       << " outer_iter= " << outer_iter << std::endl;
     583                 :            : 
     584                 :            :         // PERROR:
     585                 :            : 
     586 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( perr ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     587                 :            :         {
     588 [ #  # ][ #  # ]:          0 :             std::cout << "P[" << get_parallel_rank() << "] VertexMover::loop_over_mesh found parallel error: " << perr
         [ #  # ][ #  # ]
                 [ #  # ]
     589 [ #  # ][ #  # ]:          0 :                       << "\n quitting... pdone= " << pdone << std::endl;
                 [ #  # ]
     590                 :          0 :             pdone = true;
     591                 :            :         }
     592                 :            : 
     593         [ #  # ]:          0 :         helper->communicate_any_true( pdone, err );
     594                 :            : 
     595                 :            :         if( 0 )
     596                 :            :             std::cout << "P[" << get_parallel_rank() << "] tmp srk inner_iter= " << inner_iter
     597                 :            :                       << " outer_iter= " << outer_iter << " pdone= " << pdone << std::endl;
     598                 :            : 
     599         [ #  # ]:          0 :         if( pdone )
     600                 :            :         {
     601 [ #  # ][ #  # ]:          0 :             std::cout << "P[" << get_parallel_rank()
                 [ #  # ]
     602 [ #  # ][ #  # ]:          0 :                       << "] VertexMover::loop_over_mesh found parallel error, quitting... pdone= " << pdone
     603         [ #  # ]:          0 :                       << std::endl;
     604 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( err )( "PARALLEL ERROR", MsqError::PARALLEL_ERROR );
     605                 :          0 :             break;
     606                 :            :         }
     607                 :            : 
     608                 :          0 :         ++outer_iter;
     609                 :            : 
     610                 :            :         /// [email protected] 1/19/12: the logic here was changed so that all proc's must agree
     611                 :            :         ///   on the values used for outer and inner termination before the iteration is stopped.
     612                 :            :         ///   Previously, the ParallelHelper::communicate_all_true method returned true if any
     613                 :            :         ///   proc sent it a true value, which seems to be a bug, at least in the name of the
     614                 :            :         ///   method. The method has been changed to return true only if all proc's values are true.
     615                 :            :         ///   In the previous version, this meant that if any proc hit its inner or outer
     616                 :            :         ///   termination criterion, the loop was exited, and thus some parts of the mesh
     617                 :            :         ///   are potentially left unconverged.  Also, if the outer criterion was satisfied on
     618                 :            :         ///   part of the mesh (say a uniform part), the iterations were not executed at all.
     619                 :            :         /// Also, changed name of "did_some" to "inner_crit_terminated", and flipped its boolean
     620                 :            :         ///   value to be consistent with the name - for readability and for correctness since
     621                 :            :         ///   we want to communicate a true value through the helper.
     622                 :            : 
     623         [ #  # ]:          0 :         bool outer_crit_terminated       = outer_crit->terminate();
     624                 :          0 :         bool outer_crit_terminated_local = outer_crit_terminated;
     625         [ #  # ]:          0 :         helper->communicate_all_true( outer_crit_terminated, err );
     626                 :            : 
     627                 :          0 :         bool inner_crit_terminated_local = inner_crit_terminated;
     628         [ #  # ]:          0 :         helper->communicate_all_true( inner_crit_terminated, err );
     629                 :            : 
     630                 :          0 :         bool all_culled_local = all_culled;
     631         [ #  # ]:          0 :         helper->communicate_all_true( all_culled, err );
     632                 :            : 
     633 [ #  # ][ #  # ]:          0 :         bool done = all_culled || outer_crit_terminated;
     634         [ #  # ]:          0 :         if( inner_crit_terminated )
     635                 :            :         {
     636                 :            :             MSQ_SETERR( err )
     637                 :            :             ( "Inner termination criterion satisfied for all patches "
     638                 :            :               "without meeting outer termination criterion.  This is "
     639                 :            :               "an infinite loop.  Aborting.",
     640 [ #  # ][ #  # ]:          0 :               MsqError::INVALID_STATE );
     641                 :          0 :             done = true;
     642         [ #  # ]:          0 :             helper->communicate_any_true( done, err );
     643                 :            :         }
     644                 :            : 
     645                 :          0 :         bool local_done = done;
     646                 :            : 
     647         [ #  # ]:          0 :         helper->communicate_all_true( done, err );
     648                 :            : 
     649                 :            :         if( 0 )
     650                 :            :             std::cout << "P[" << get_parallel_rank() << "] tmp srk done= " << done << " local_done= " << local_done
     651                 :            :                       << " all_culled= " << all_culled << " outer_crit->terminate()= " << outer_crit->terminate()
     652                 :            :                       << " outer_term= " << outer_crit_terminated
     653                 :            :                       << " outer_term_local= " << outer_crit_terminated_local
     654                 :            :                       << " inner_crit_terminated = " << inner_crit_terminated
     655                 :            :                       << " inner_crit_terminated_local = " << inner_crit_terminated_local
     656                 :            :                       << " all_culled = " << all_culled << " all_culled_local = " << all_culled_local << std::endl;
     657                 :            : 
     658 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) ) { MSQ_SETERR( perr )( "loop start", MsqError::INVALID_STATE ); }  // goto ERROR;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     659                 :            : 
     660         [ #  # ]:          0 :         if( done ) break;
     661                 :            : 
     662                 :          0 :         inner_crit_terminated = true;
     663                 :          0 :         all_culled            = true;
     664                 :            : 
     665                 :            :         ///*** smooth the interior ***////
     666                 :            : 
     667                 :            :         // get the fixed vertices (i.e. the ones *not* part of the first independent set)
     668         [ #  # ]:          0 :         helper->compute_first_independent_set( fixed_vertices );
     669                 :            : 
     670                 :            :         // sort the fixed vertices
     671         [ #  # ]:          0 :         std::sort( fixed_vertices.begin(), fixed_vertices.end() );
     672                 :            : 
     673                 :            :         // Loop over each patch
     674                 :            :         if( 0 && MSQ_DBG( 2 ) )
     675                 :            :             std::cout << "P[" << get_parallel_rank() << "] tmp srk number of patches = " << patch_list.size()
     676                 :            :                       << " inner_iter= " << inner_iter << " outer_iter= " << outer_iter
     677                 :            :                       << " inner.globalInvertedCount = " << inner_crit->globalInvertedCount
     678                 :            :                       << " outer.globalInvertedCount = " << outer_crit->globalInvertedCount
     679                 :            :                       << " inner.patchInvertedCount = " << inner_crit->patchInvertedCount
     680                 :            :                       << " outer.patchInvertedCount = " << outer_crit->patchInvertedCount << std::endl;
     681                 :            : 
     682         [ #  # ]:          0 :         save_or_restore_debug_state( true );
     683                 :            :         // MsqDebug::disable_all();
     684                 :            : 
     685                 :          0 :         int num_patches = 0;
     686                 :            : 
     687                 :          0 :         std::vector< PatchSet::PatchHandle >::iterator p_iter = patch_list.begin();
     688 [ #  # ][ #  # ]:          0 :         while( p_iter != patch_list.end() )
     689                 :            :         {
     690                 :            : 
     691                 :            :             // loop until we get a non-empty patch.  patch will be empty
     692                 :            :             // for culled vertices with element-on-vertex patches
     693         [ #  # ]:          0 :             do
     694                 :            :             {
     695 [ #  # ][ #  # ]:          0 :                 patch_set->get_patch( *p_iter, patch_elements, patch_vertices, err );
     696 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     697                 :            :                 {
     698 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "get_patch", MsqError::INVALID_STATE );
     699                 :          0 :                     PERROR_COND;
     700                 :            :                 }  // goto ERROR;
     701         [ #  # ]:          0 :                 ++p_iter;
     702 [ #  # ][ #  # ]:          0 :             } while( patch_elements.empty() && p_iter != patch_list.end() );
         [ #  # ][ #  # ]
                 [ #  # ]
     703                 :            : 
     704         [ #  # ]:          0 :             if( patch_elements.empty() )
     705                 :            :             {  // no more non-culled vertices
     706                 :            :                 if( 0 ) std::cout << "P[" << get_parallel_rank() << "] tmp srk all vertices culled." << std::endl;
     707                 :          0 :                 break;
     708                 :            :             }
     709                 :            : 
     710         [ #  # ]:          0 :             if( patch_vertices.empty() )  // global patch hack (means all mesh vertices)
     711         [ #  # ]:          0 :             { mesh->get_all_vertices( patch_vertices, err ); }
     712                 :            : 
     713                 :          0 :             free_vertices.clear();
     714                 :            : 
     715         [ #  # ]:          0 :             for( size_t i = 0; i < patch_vertices.size(); ++i )
     716 [ #  # ][ #  # ]:          0 :                 if( !std::binary_search( fixed_vertices.begin(), fixed_vertices.end(), patch_vertices[i] ) )
                 [ #  # ]
     717 [ #  # ][ #  # ]:          0 :                     free_vertices.push_back( patch_vertices[i] );
     718                 :            : 
     719         [ #  # ]:          0 :             if( free_vertices.empty() )
     720                 :            :             {  // all vertices were fixed -> skip patch
     721                 :          0 :                 continue;
     722                 :            :             }
     723                 :            : 
     724                 :          0 :             ++num_patches;
     725                 :          0 :             all_culled = false;
     726         [ #  # ]:          0 :             patch.set_mesh_entities( patch_elements, free_vertices, err );
     727 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     728                 :            :             {
     729 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( perr )( "set_mesh_entities", MsqError::INVALID_STATE );
     730                 :          0 :                 PERROR_COND;
     731                 :            :             }  // goto ERROR;
     732                 :            : 
     733                 :            :             // Initialize for inner iteration
     734                 :            : 
     735         [ #  # ]:          0 :             this->initialize_mesh_iteration( patch, err );
     736 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     737                 :            :             {
     738 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( perr )( "initialize_mesh_iteration", MsqError::INVALID_STATE );
     739                 :          0 :                 PERROR_COND;
     740                 :            :             }  // goto ERROR;
     741                 :            : 
     742         [ #  # ]:          0 :             obj_func.reset();
     743                 :            : 
     744         [ #  # ]:          0 :             outer_crit->reset_patch( patch, err );
     745 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     746                 :            :             {
     747 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( perr )( "reset_patch outer", MsqError::INVALID_STATE );
     748                 :          0 :                 PERROR_COND;
     749                 :            :             }  // goto ERROR;
     750                 :            : 
     751         [ #  # ]:          0 :             inner_crit->reset_inner( patch, obj_func, err );
     752 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     753                 :            :             {
     754 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( perr )( "reset_inner", MsqError::INVALID_STATE );
     755                 :          0 :                 PERROR_COND;
     756                 :            :             }  // goto ERROR;
     757                 :            : 
     758         [ #  # ]:          0 :             inner_crit->reset_patch( patch, err );
     759 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     760                 :            :             {
     761 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( perr )( "inner reset_patch", MsqError::INVALID_STATE );
     762                 :          0 :                 PERROR_COND;
     763                 :            :             }  // goto ERROR;
     764                 :            : 
     765                 :            :             // Don't even call optimizer if inner termination
     766                 :            :             // criterion has already been met.
     767 [ #  # ][ #  # ]:          0 :             if( !inner_crit->terminate() )
     768                 :            :             {
     769                 :          0 :                 inner_crit_terminated = false;
     770         [ #  # ]:          0 :                 if( one_patch ) ++inner_iter;
     771                 :            : 
     772                 :            :                 // Call optimizer - should loop on inner_crit->terminate()
     773                 :            :                 // size_t num_vert=patch.num_free_vertices();
     774                 :            :                 // std::cout << "P[" << get_parallel_rank() << "] tmp srk VertexMover num_vert= " <<
     775                 :            :                 // num_vert << std::endl;
     776                 :            : 
     777         [ #  # ]:          0 :                 this->optimize_vertex_positions( patch, err );
     778 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     779                 :            :                 {
     780 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "optimize_vertex_positions", MsqError::INVALID_STATE );
     781                 :          0 :                     PERROR_COND;
     782                 :            :                 }  // goto ERROR;
     783                 :            : 
     784                 :            :                 // Update for changes during inner iteration
     785                 :            :                 // (during optimizer loop)
     786                 :            : 
     787         [ #  # ]:          0 :                 outer_crit->accumulate_patch( patch, err );
     788 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     789                 :            :                 {
     790 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "outer accumulate_patch", MsqError::INVALID_STATE );
     791                 :          0 :                     PERROR_COND;
     792                 :            :                 }  // goto ERROR;
     793                 :            : 
     794         [ #  # ]:          0 :                 inner_crit->cull_vertices( patch, obj_func, err );
     795 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     796                 :            :                 {
     797 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "inner cull_vertices", MsqError::INVALID_STATE );
     798                 :          0 :                     PERROR_COND;
     799                 :            :                 }  // goto ERROR;
     800                 :            : 
     801                 :            :                 // experimental...
     802                 :            :                 if( 0 )
     803                 :            :                 {
     804                 :            :                     inner_crit->cull_vertices_global( patch, mesh, domain, settings, obj_func, err );
     805                 :            :                     if( MSQ_CHKERR( err ) )
     806                 :            :                     {
     807                 :            :                         MSQ_SETERR( perr )( "cull_vertices_global", MsqError::INVALID_STATE );
     808                 :            :                         PERROR_COND;
     809                 :            :                     }  // goto ERROR;
     810                 :            :                 }
     811                 :            : 
     812         [ #  # ]:          0 :                 patch.update_mesh( err, coord_tag_ptr );
     813 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     814                 :            :                 {
     815 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "update_mesh", MsqError::INVALID_STATE );
     816                 :          0 :                     PERROR_COND;
     817                 :            :                 }  // goto ERROR;
     818                 :            :             }
     819                 :            :         }  // while(p_iter....
     820                 :            : 
     821         [ #  # ]:          0 :         save_or_restore_debug_state( false );
     822                 :            : 
     823                 :            :         if( 1 )
     824                 :            :         {
     825                 :          0 :             bool pdone_inner = false;
     826                 :            : 
     827 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( perr ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     828                 :            :             {
     829 [ #  # ][ #  # ]:          0 :                 std::cout << "P[" << get_parallel_rank()
                 [ #  # ]
     830 [ #  # ][ #  # ]:          0 :                           << "] VertexMover::loop_over_mesh found parallel error: " << perr
     831 [ #  # ][ #  # ]:          0 :                           << "\n quitting... pdone_inner= " << pdone_inner << std::endl;
                 [ #  # ]
     832                 :          0 :                 pdone_inner = true;
     833                 :            :             }
     834                 :            : 
     835         [ #  # ]:          0 :             helper->communicate_any_true( pdone_inner, err );
     836                 :            : 
     837                 :            :             if( 0 )
     838                 :            :                 std::cout << "P[" << get_parallel_rank() << "] tmp srk inner_iter= " << inner_iter
     839                 :            :                           << " outer_iter= " << outer_iter << " pdone_inner= " << pdone_inner << std::endl;
     840                 :            : 
     841         [ #  # ]:          0 :             if( pdone_inner )
     842                 :            :             {
     843                 :            :                 if( 0 )
     844                 :            :                     std::cout << "P[" << get_parallel_rank()
     845                 :            :                               << "] tmp srk found parallel error, quitting... pdone_inner= " << pdone_inner
     846                 :            :                               << std::endl;
     847 [ #  # ][ #  # ]:          0 :                 MSQ_SETERR( err )( "PARALLEL ERROR", MsqError::PARALLEL_ERROR );
     848                 :          0 :                 break;
     849                 :            :             }
     850                 :            :         }
     851                 :            : 
     852                 :            :         /// [email protected] save vertex bytes since boundary smoothing changes them
     853         [ #  # ]:          0 :         std::vector< unsigned char > saved_bytes;
     854 [ #  # ][ #  # ]:          0 :         checkpoint_bytes( mesh, saved_bytes, err );
     855 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     856                 :            :         {
     857 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( perr )( "checkpoint_bytes ", MsqError::INVALID_STATE );
     858                 :          0 :             PERROR_COND;
     859                 :            :         }  // goto ERROR;
     860                 :            : 
     861         [ #  # ]:          0 :         helper->communicate_first_independent_set( err );
     862 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     863                 :            :         {
     864 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( perr )( "communicate_first_independent_set ", MsqError::INVALID_STATE );
     865                 :          0 :             PERROR_COND;
     866                 :            :         }  // goto ERROR;
     867                 :            : 
     868                 :            :         ///*** smooth the boundary ***////
     869         [ #  # ]:          0 :         save_or_restore_debug_state( true );
     870         [ #  # ]:          0 :         MsqDebug::disable_all();
     871                 :            : 
     872 [ #  # ][ #  # ]:          0 :         while( helper->compute_next_independent_set() )
     873                 :            :         {
     874                 :            :             // Loop over all boundary elements
     875 [ #  # ][ #  # ]:          0 :             while( helper->get_next_partition_boundary_vertex( vertex_handle ) )
     876                 :            :             {
     877                 :            : 
     878                 :          0 :                 patch_vertices.clear();
     879         [ #  # ]:          0 :                 patch_vertices.push_back( vertex_handle );
     880                 :          0 :                 patch_elements.clear();
     881         [ #  # ]:          0 :                 mesh->vertices_get_attached_elements( &vertex_handle, 1, patch_elements, junk, err );
     882                 :            : 
     883                 :          0 :                 all_culled = false;
     884         [ #  # ]:          0 :                 patch.set_mesh_entities( patch_elements, patch_vertices, err );
     885                 :            : 
     886 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     887                 :            :                 {
     888 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "set_mesh_entities 2 ", MsqError::INVALID_STATE );
     889                 :          0 :                     PERROR_COND;
     890                 :            :                 }  // goto ERROR;
     891                 :            : 
     892                 :            :                 // Initialize for inner iteration
     893                 :            : 
     894         [ #  # ]:          0 :                 this->initialize_mesh_iteration( patch, err );
     895 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     896                 :            :                 {
     897 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( " initialize_mesh_iteration 2", MsqError::INVALID_STATE );
     898                 :          0 :                     PERROR_COND;
     899                 :            :                 }  // goto ERROR;
     900                 :            : 
     901         [ #  # ]:          0 :                 obj_func.reset();
     902                 :            : 
     903         [ #  # ]:          0 :                 outer_crit->reset_patch( patch, err );
     904 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     905                 :            :                 {
     906 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( "outer reset_patch 2 ", MsqError::INVALID_STATE );
     907                 :          0 :                     PERROR_COND;
     908                 :            :                 }  // goto ERROR;
     909                 :            : 
     910         [ #  # ]:          0 :                 inner_crit->reset_inner( patch, obj_func, err );
     911 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     912                 :            :                 {
     913 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( " inner reset_inner 2", MsqError::INVALID_STATE );
     914                 :          0 :                     PERROR_COND;
     915                 :            :                 }  // goto ERROR;
     916                 :            : 
     917         [ #  # ]:          0 :                 inner_crit->reset_patch( patch, err );
     918 [ #  # ][ #  # ]:          0 :                 if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     919                 :            :                 {
     920 [ #  # ][ #  # ]:          0 :                     MSQ_SETERR( perr )( " inner_crit reset_patch 2", MsqError::INVALID_STATE );
     921                 :          0 :                     PERROR_COND;
     922                 :            :                 }  // goto ERROR;
     923                 :            : 
     924                 :            :                 // Don't even call optimizer if inner termination
     925                 :            :                 // criterion has already been met.
     926 [ #  # ][ #  # ]:          0 :                 if( !inner_crit->terminate() )
     927                 :            :                 {
     928                 :          0 :                     inner_crit_terminated = false;
     929                 :            : 
     930                 :            :                     // Call optimizer - should loop on inner_crit->terminate()
     931         [ #  # ]:          0 :                     this->optimize_vertex_positions( patch, err );
     932 [ #  # ][ #  # ]:          0 :                     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     933                 :            :                     {
     934                 :            :                         MSQ_SETERR( perr )
     935 [ #  # ][ #  # ]:          0 :                         ( " optimize_vertex_positions 2", MsqError::INVALID_STATE );
     936                 :          0 :                         PERROR_COND;
     937                 :            :                     }  // goto ERROR;
     938                 :            : 
     939                 :            :                     // Update for changes during inner iteration
     940                 :            :                     // (during optimizer loop)
     941                 :            : 
     942         [ #  # ]:          0 :                     outer_crit->accumulate_patch( patch, err );
     943 [ #  # ][ #  # ]:          0 :                     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     944                 :            :                     {
     945 [ #  # ][ #  # ]:          0 :                         MSQ_SETERR( perr )( " outer accumulate_patch 2", MsqError::INVALID_STATE );
     946                 :          0 :                         PERROR_COND;
     947                 :            :                     }  // goto ERROR;
     948                 :            : 
     949         [ #  # ]:          0 :                     inner_crit->cull_vertices( patch, obj_func, err );
     950 [ #  # ][ #  # ]:          0 :                     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     951                 :            :                     {
     952 [ #  # ][ #  # ]:          0 :                         MSQ_SETERR( perr )( " inner cull_vertices", MsqError::INVALID_STATE );
     953                 :          0 :                         PERROR_COND;
     954                 :            :                     }  // goto ERROR;
     955                 :            : 
     956                 :            :                     // FIXME
     957                 :            :                     if( 0 )
     958                 :            :                     {
     959                 :            :                         inner_crit->cull_vertices_global( patch, mesh, domain, settings, obj_func, err );
     960                 :            :                         if( MSQ_CHKERR( err ) )
     961                 :            :                         {
     962                 :            :                             MSQ_SETERR( perr )
     963                 :            :                             ( " cull_vertices_global 2 ", MsqError::INVALID_STATE );
     964                 :            :                             PERROR_COND;
     965                 :            :                         }  // goto ERROR;
     966                 :            :                     }
     967                 :            : 
     968         [ #  # ]:          0 :                     patch.update_mesh( err, coord_tag_ptr );
     969 [ #  # ][ #  # ]:          0 :                     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     970                 :            :                     {
     971 [ #  # ][ #  # ]:          0 :                         MSQ_SETERR( perr )( " update_mesh 2", MsqError::INVALID_STATE );
     972                 :          0 :                         PERROR_COND;
     973                 :            :                     }  // goto ERROR;
     974                 :            :                 }
     975                 :            :             }
     976         [ #  # ]:          0 :             helper->communicate_next_independent_set( err );
     977 [ #  # ][ #  # ]:          0 :             if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     978                 :            :             {
     979                 :            :                 MSQ_SETERR( perr )
     980 [ #  # ][ #  # ]:          0 :                 ( " communicate_next_independent_set 2", MsqError::INVALID_STATE );
     981                 :          0 :                 PERROR_COND;
     982                 :            :             }  // goto ERROR;
     983                 :            :         }      // while(helper->compute_next_independent_set())
     984                 :            : 
     985         [ #  # ]:          0 :         save_or_restore_debug_state( false );
     986                 :            : 
     987                 :            :         // if (!get_parallel_rank())
     988                 :            :         // std::cout << "P[" << get_parallel_rank() << "] tmp srk num_patches= " << num_patches <<
     989                 :            :         // std::endl;
     990                 :            : 
     991                 :            :         /// [email protected] restore vertex bytes since boundary smoothing changes them
     992 [ #  # ][ #  # ]:          0 :         restore_bytes( mesh, saved_bytes, err );
     993 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     994                 :            :         {
     995 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( perr )( " restore_bytes", MsqError::INVALID_STATE );
     996                 :          0 :             PERROR_COND;
     997                 :            :         }  // goto ERROR;
     998                 :            : 
     999 [ #  # ][ #  # ]:          0 :         if( jacobiOpt ) commit_jacobi_coords( coord_tag, mesh, err );
                 [ #  # ]
    1000                 :            : 
    1001         [ #  # ]:          0 :         this->terminate_mesh_iteration( patch, err );
    1002 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1003                 :            :         {
    1004 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( perr )( " terminate_mesh_iteration", MsqError::INVALID_STATE );
    1005                 :          0 :             PERROR_COND;
    1006                 :            :         }  // goto ERROR;
    1007                 :            : 
    1008 [ #  # ][ #  # ]:          0 :         outer_crit->accumulate_outer( mesh, domain, obj_func, settings, err );
    1009 [ #  # ][ #  # ]:          0 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1010                 :            :         {
    1011 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( perr )( " outer_crit accumulate_outer", MsqError::INVALID_STATE );
    1012         [ #  # ]:          0 :             PERROR_COND;
    1013                 :            :         }  // goto ERROR;
    1014                 :          0 :     }
    1015                 :            : 
    1016                 :            :     // ERROR:
    1017                 :            : 
    1018 [ #  # ][ #  # ]:          0 :     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1019                 :            :     {
    1020 [ #  # ][ #  # ]:          0 :         std::cout << "P[" << get_parallel_rank() << "] VertexMover::loop_over_mesh error = " << err.error_message()
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1021         [ #  # ]:          0 :                   << std::endl;
    1022                 :            :     }
    1023                 :            : 
    1024 [ #  # ][ #  # ]:          0 :     if( jacobiOpt ) mesh->tag_delete( coord_tag, err );
    1025                 :            : 
    1026                 :            :     // call the criteria's cleanup funtions.
    1027 [ #  # ][ #  # ]:          0 :     outer_crit->cleanup( mesh, domain, err );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1028 [ #  # ][ #  # ]:          0 :     inner_crit->cleanup( mesh, domain, err );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1029                 :            :     // call the optimization cleanup function.
    1030         [ #  # ]:          0 :     this->cleanup();
    1031                 :            :     // close the helper
    1032 [ #  # ][ #  # ]:          0 :     helper->smoothing_close( err );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1033                 :            : 
    1034                 :          0 :     return 0.;
    1035                 :            : }
    1036                 :            : 
    1037                 :        130 : void VertexMover::initialize_queue( MeshDomainAssoc* mesh_and_domain, const Settings* settings, MsqError& err )
    1038                 :            : {
    1039 [ -  + ][ #  # ]:        130 :     QualityImprover::initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
                 [ -  + ]
    1040 [ -  + ][ #  # ]:        130 :     objFuncEval.initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
                 [ -  + ]
    1041                 :            : }
    1042                 :            : 
    1043                 :          1 : TagHandle VertexMover::get_jacobi_coord_tag( Mesh* mesh, MsqError& err )
    1044                 :            : {
    1045                 :            :     // Get tag handle
    1046                 :          1 :     const char tagname[] = "msq_jacobi_temp_coords";
    1047 [ +  - ][ +  - ]:          1 :     TagHandle tag        = mesh->tag_create( tagname, Mesh::DOUBLE, 3, 0, err );
    1048 [ +  - ][ -  + ]:          1 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    1049                 :            :     /* VertexMover will always delete the tag when it is done, so it is probably
    1050                 :            :        best not to accept an existing tag
    1051                 :            :   if (err.error_code() == TAG_ALREADY_EXISTS) {
    1052                 :            :     err.clear();
    1053                 :            :     tag = tag_get( tagname, err ); MSQ_ERRZERO(err);
    1054                 :            :     std::string name;
    1055                 :            :     Mesh::TagType type;
    1056                 :            :     unsigned length;
    1057                 :            :     mesh->tag_properties( tag, name, type, length, err ); MSQ_ERRZERO(err);
    1058                 :            :     if (type != Mesh::DOUBLE || length != 3) {
    1059                 :            :       MSQ_SETERR(err)(TAG_ALREADY_EXISTS,
    1060                 :            :                      "Tag \"%s\" already exists with invalid type",
    1061                 :            :                      tagname);
    1062                 :            :       return 0;
    1063                 :            :     }
    1064                 :            :   }
    1065                 :            :     */
    1066                 :            : 
    1067                 :            :     // Initialize tag value with initial vertex coordinates so that
    1068                 :            :     // vertices that never get moved end up with the correct coords.
    1069         [ +  - ]:          1 :     std::vector< Mesh::VertexHandle > vertices;
    1070         [ +  - ]:          1 :     mesh->get_all_vertices( vertices, err );
    1071 [ +  - ][ -  + ]:          1 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    1072                 :            :     // remove fixed vertices
    1073                 :            :     // to avoid really huge arrays (especially since we need to copy
    1074                 :            :     // coords out of annoying MsqVertex class to double array), work
    1075                 :            :     // in blocks
    1076                 :          1 :     const size_t blocksize = 4096;
    1077         [ +  - ]:          2 :     std::vector< bool > fixed( blocksize );
    1078 [ +  - ][ +  + ]:       4097 :     MsqVertex coords[blocksize];
    1079                 :            :     double tag_data[3 * blocksize];
    1080         [ +  + ]:          2 :     for( size_t i = 0; i < vertices.size(); i += blocksize )
    1081                 :            :     {
    1082         [ +  - ]:          1 :         size_t count = std::min( blocksize, vertices.size() - i );
    1083                 :            :         // remove fixed vertices
    1084 [ +  - ][ +  - ]:          1 :         mesh->vertices_get_fixed_flag( &vertices[i], fixed, count, err );
    1085 [ +  - ][ -  + ]:          1 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    1086                 :          1 :         size_t w = 0;
    1087         [ +  + ]:         17 :         for( size_t j = 0; j < count; ++j )
    1088 [ +  - ][ +  + ]:         16 :             if( !fixed[j] ) vertices[i + w++] = vertices[i + j];
         [ +  - ][ +  - ]
    1089                 :          1 :         count = w;
    1090                 :            :         // store tag data for free vertices
    1091 [ +  - ][ +  - ]:          1 :         mesh->vertices_get_coordinates( &vertices[i], coords, count, err );
    1092 [ +  - ][ -  + ]:          1 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    1093         [ +  + ]:          5 :         for( size_t j = 0; j < count; ++j )
    1094                 :            :         {
    1095         [ +  - ]:          4 :             tag_data[3 * j]     = coords[j][0];
    1096         [ +  - ]:          4 :             tag_data[3 * j + 1] = coords[j][1];
    1097         [ +  - ]:          4 :             tag_data[3 * j + 2] = coords[j][2];
    1098                 :            :         }
    1099 [ +  - ][ +  - ]:          1 :         mesh->tag_set_vertex_data( tag, count, &vertices[i], tag_data, err );
    1100 [ +  - ][ -  + ]:          1 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    1101                 :            :     }
    1102                 :            : 
    1103                 :          2 :     return tag;
    1104                 :            : }
    1105                 :            : 
    1106                 :          1 : void VertexMover::commit_jacobi_coords( TagHandle tag, Mesh* mesh, MsqError& err )
    1107                 :            : {
    1108         [ +  - ]:          1 :     Vector3D coords;
    1109         [ +  - ]:          1 :     std::vector< Mesh::VertexHandle > vertices;
    1110 [ +  - ][ +  - ]:          1 :     mesh->get_all_vertices( vertices, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1111 [ +  - ][ +  - ]:          2 :     std::vector< bool > fixed( vertices.size() );
    1112 [ +  - ][ +  - ]:          1 :     mesh->vertices_get_fixed_flag( &vertices[0], fixed, vertices.size(), err );
    1113 [ +  + ][ +  - ]:         17 :     for( size_t i = 0; i < vertices.size(); ++i )
    1114                 :            :     {
    1115 [ +  - ][ +  + ]:         16 :         if( !fixed[i] )
    1116                 :            :         {
    1117 [ +  - ][ +  - ]:          4 :             mesh->tag_get_vertex_data( tag, 1, &vertices[i], coords.to_array(), err );MSQ_ERRRTN( err );
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1118 [ +  - ][ +  - ]:          4 :             mesh->vertex_set_coordinates( vertices[i], coords, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
    1119                 :            :         }
    1120                 :          1 :     }
    1121                 :            : }
    1122                 :            : 
    1123 [ +  - ][ +  - ]:        120 : }  // namespace MBMesquite

Generated by: LCOV version 1.11