MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2004 Sandia Corporation and Argonne National 00005 Laboratory. Under the terms of Contract DE-AC04-94AL85000 00006 with Sandia Corporation, the U.S. Government retains certain 00007 rights in this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 [email protected], [email protected], [email protected], 00024 [email protected], [email protected], [email protected] 00025 00026 ***************************************************************** */ 00027 // -*- Mode : c++; tab-width: 3; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 3 00028 // -*- 00029 00030 /*! \file InstructionQueue.cpp 00031 00032 Member functions of the MBMesquite::InstructionQueue class 00033 00034 \author Thomas Leurent 00035 \date 2002-05-01 00036 */ 00037 00038 #include <string> 00039 #include <list> 00040 #include <memory> 00041 00042 #include "InstructionQueue.hpp" 00043 #include "MsqInterrupt.hpp" 00044 #include "QualityImprover.hpp" 00045 #include "QualityAssessor.hpp" 00046 #include "TargetWriter.hpp" 00047 #include "VertexSlaver.hpp" 00048 #include "TagVertexMesh.hpp" 00049 #include "MsqError.hpp" 00050 #include "MsqDebug.hpp" 00051 #include "MsqFPE.hpp" 00052 #include "ParallelMeshInterface.hpp" 00053 00054 using namespace MBMesquite; 00055 00056 InstructionQueue::InstructionQueue() 00057 : autoQualAssess( true ), vertexSlaverCount( 0 ), nbPreConditionners( 0 ), isMasterSet( false ), 00058 masterInstrIndex( 0 ) 00059 { 00060 } 00061 00062 InstructionQueue::~InstructionQueue() {} 00063 00064 void InstructionQueue::add_target_calculator( TargetWriter* tc, MsqError& ) 00065 { 00066 instructions.push_back( tc ); 00067 } 00068 00069 void InstructionQueue::add_vertex_slaver( VertexSlaver* vs, MsqError& ) 00070 { 00071 instructions.push_front( vs ); 00072 if( isMasterSet ) ++masterInstrIndex; 00073 ++vertexSlaverCount; 00074 set_slaved_ho_node_mode( Settings::SLAVE_CALCULATED ); 00075 } 00076 00077 void InstructionQueue::remove_vertex_slaver( VertexSlaver* vs, MsqError& err ) 00078 { 00079 size_t idx = 0; 00080 for( std::list< Instruction* >::iterator i = instructions.begin(); i != instructions.end(); ++i, ++idx ) 00081 { 00082 if( *i == vs ) 00083 { 00084 instructions.erase( i ); 00085 if( isMasterSet && masterInstrIndex > idx ) --masterInstrIndex; 00086 if( --vertexSlaverCount == 0 ) set_slaved_ho_node_mode( Settings::SLAVE_ALL ); 00087 return; 00088 } 00089 } 00090 00091 MSQ_SETERR( err )( "Not found", MsqError::INVALID_ARG ); 00092 } 00093 00094 void InstructionQueue::add_tag_vertex_mesh( TagVertexMesh* vs, MsqError& ) 00095 { 00096 instructions.push_front( vs ); 00097 if( isMasterSet ) ++masterInstrIndex; 00098 } 00099 00100 void InstructionQueue::remove_tag_vertex_mesh( TagVertexMesh* vs, MsqError& err ) 00101 { 00102 size_t idx = 0; 00103 for( std::list< Instruction* >::iterator i = instructions.begin(); i != instructions.end(); ++i, ++idx ) 00104 { 00105 if( *i == vs ) 00106 { 00107 instructions.erase( i ); 00108 if( isMasterSet && masterInstrIndex > idx ) --masterInstrIndex; 00109 return; 00110 } 00111 } 00112 00113 MSQ_SETERR( err )( "Not found", MsqError::INVALID_ARG ); 00114 } 00115 00116 /*! \fn InstructionQueue::add_preconditioner(QualityImprover* instr, MsqError &err) 00117 \brief adds a QualityImprover at the end of the instruction list 00118 00119 This function cannot be used once the set_master_quality_improver() 00120 function has been used. 00121 00122 See also insert_preconditioner(). 00123 */ 00124 void InstructionQueue::add_preconditioner( QualityImprover* instr, MsqError& err ) 00125 { 00126 if( isMasterSet ) 00127 { 00128 MSQ_SETERR( err ) 00129 ( "Cannot add preconditioners once the master " 00130 "QualityImprover has been set.", 00131 MsqError::INVALID_STATE ); 00132 return; 00133 } 00134 00135 instructions.push_back( instr ); 00136 nbPreConditionners++; 00137 } 00138 00139 /*! \fn InstructionQueue::remove_preconditioner(size_t index, MsqError &err) 00140 \brief removes a QualityImprover* from the instruction queue 00141 00142 \param index is 0-based. An error is set if the index does not correspond 00143 to a valid element in the queue. 00144 */ 00145 void InstructionQueue::remove_preconditioner( size_t index, MsqError& err ) 00146 { 00147 // checks index is valid 00148 if( isMasterSet && index == masterInstrIndex ) 00149 { 00150 MSQ_SETERR( err )( "cannot remove master QualityImprover.", MsqError::INVALID_ARG ); 00151 return; 00152 } 00153 else if( index >= instructions.size() ) 00154 { 00155 MSQ_SETERR( err )( "Index points beyond end of list.", MsqError::INVALID_ARG ); 00156 return; 00157 } 00158 00159 // position the instruction iterator over the preconditioner to delete 00160 std::list< Instruction* >::iterator pos; 00161 pos = instructions.begin(); 00162 std::advance( pos, index ); 00163 00164 if( !dynamic_cast< QualityImprover* >( *pos ) ) 00165 { 00166 MSQ_SETERR( err )( "Index does not point to a QualityImprover.", MsqError::INVALID_ARG ); 00167 return; 00168 } 00169 00170 std::string name = ( *pos )->get_name(); 00171 instructions.erase( pos ); 00172 nbPreConditionners--; 00173 } 00174 00175 /*! \fn InstructionQueue::insert_preconditioner(QualityImprover* instr, size_t index, MsqError &err) 00176 \brief inserts a QualityImprover* into the instruction queue. 00177 00178 Pre-conditionners can only be inserted before the master QualityImprover. 00179 00180 \param index is 0-based. An error is set if the index does not correspond 00181 to a valid position in the queue. 00182 */ 00183 void InstructionQueue::insert_preconditioner( QualityImprover* instr, size_t index, MsqError& err ) 00184 { 00185 // checks index is valid 00186 if( isMasterSet == true && index > masterInstrIndex ) 00187 { 00188 MSQ_SETERR( err ) 00189 ( "Cannot add a preconditioner after the master " 00190 "QualityImprover.", 00191 MsqError::INVALID_STATE ); 00192 return; 00193 } 00194 if( index >= instructions.size() ) 00195 { 00196 MSQ_SETERR( err )( "index", MsqError::INVALID_ARG ); 00197 return; 00198 } 00199 00200 // position the instruction iterator 00201 std::list< Instruction* >::iterator pos; 00202 pos = instructions.begin(); 00203 std::advance( pos, index ); 00204 // adds the preconditioner 00205 instructions.insert( pos, instr ); 00206 nbPreConditionners++; 00207 } 00208 00209 /*! \fn InstructionQueue::add_quality_assessor(QualityAssessor* instr, MsqError &err) 00210 \brief adds a QualityAssessor to the instruction queue. 00211 00212 QualityAssessor pointers can be added at any time to the instruction queue. 00213 */ 00214 void InstructionQueue::add_quality_assessor( QualityAssessor* instr, MsqError& /*err*/ ) 00215 { 00216 instructions.push_back( instr ); 00217 } 00218 00219 /*! \fn InstructionQueue::remove_quality_assessor(size_t index, MsqError &err) 00220 \brief removes a QualityAssessor* from the instruction queue 00221 00222 \param index is 0-based. An error is set if the index does not correspond 00223 to a valid element in the queue. 00224 */ 00225 void InstructionQueue::remove_quality_assessor( size_t index, MsqError& err ) 00226 { 00227 // checks index is valid 00228 if( index >= instructions.size() ) 00229 { 00230 MSQ_SETERR( err )( "index", MsqError::INVALID_ARG ); 00231 return; 00232 } 00233 00234 // position the instruction iterator over the QualityAssessor to delete 00235 std::list< Instruction* >::iterator pos; 00236 pos = instructions.begin(); 00237 std::advance( pos, index ); 00238 00239 if( !dynamic_cast< QualityAssessor* >( *pos ) ) 00240 { 00241 MSQ_SETERR( err )( "Index does not point to a QualityImprover.", MsqError::INVALID_ARG ); 00242 return; 00243 } 00244 00245 std::string name = ( *pos )->get_name(); 00246 instructions.erase( pos ); 00247 } 00248 00249 /*! \fn InstructionQueue::insert_quality_assessor(QualityAssessor* instr, size_t index, MsqError 00250 &err) \brief inserts a QualityAssessor* into the instruction queue. 00251 00252 QualityAssessors can be inserted at any position in the instruction queue. 00253 00254 \param index is 0-based. An error is set if the index is past the end of the queue. 00255 */ 00256 void InstructionQueue::insert_quality_assessor( QualityAssessor* instr, size_t index, MsqError& err ) 00257 { 00258 // checks index is valid 00259 if( index > instructions.size() ) 00260 { 00261 MSQ_SETERR( err ) 00262 ( "index points two positions beyond end of list.", MsqError::INVALID_ARG ); 00263 return; 00264 } 00265 00266 // position the instruction iterator 00267 std::list< Instruction* >::iterator pos; 00268 pos = instructions.begin(); 00269 std::advance( pos, index ); 00270 // adds the QualityAssessor 00271 instructions.insert( pos, instr ); 00272 } 00273 00274 void InstructionQueue::set_master_quality_improver( QualityImprover* instr, MsqError& err ) 00275 { 00276 if( isMasterSet ) 00277 { 00278 MSQ_DBGOUT( 1 ) << "InstructionQueue::set_master_quality_improver():\n" 00279 << "\tOverwriting previously specified master quality improver.\n"; 00280 // if master is already set, clears it and insert the new one at the same position. 00281 std::list< Instruction* >::iterator master_pos; 00282 master_pos = this->clear_master( err );MSQ_ERRRTN( err ); 00283 instructions.insert( master_pos, instr ); 00284 isMasterSet = true; 00285 } 00286 else 00287 { 00288 // if master is not set, add it at the end of the queue. 00289 instructions.push_back( instr ); 00290 isMasterSet = true; 00291 masterInstrIndex = instructions.size() - 1; 00292 } 00293 } 00294 00295 void InstructionQueue::run_common( MeshDomainAssoc* mesh_and_domain, 00296 ParallelMesh* pmesh, 00297 Settings* settings, 00298 MsqError& err ) 00299 { 00300 MSQ_DBGOUT( 1 ) << version_string( false ) << "\n"; 00301 00302 if( nbPreConditionners != 0 && isMasterSet == false ) 00303 { 00304 MSQ_SETERR( err ) 00305 ( "no pre-conditionners allowed if master QualityImprover " 00306 "is not set.", 00307 MsqError::INVALID_STATE ); 00308 return; 00309 } 00310 00311 #ifdef ENABLE_INTERRUPT 00312 // Register SIGINT handler 00313 MsqInterrupt msq_interrupt; 00314 #endif 00315 00316 Mesh* mesh = mesh_and_domain->get_mesh(); 00317 MeshDomain* domain = mesh_and_domain->get_domain(); 00318 00319 // Generate SIGFPE on floating point errors 00320 MsqFPE fpe_trap( settings->trap_floating_point_exception() ); 00321 00322 std::list< Instruction* >::const_iterator instr; 00323 00324 // Initialize each instruction 00325 for( instr = instructions.begin(); instr != instructions.end(); ++instr ) 00326 { 00327 if( MsqInterrupt::interrupt() ) 00328 { 00329 MSQ_SETERR( err )( MsqError::INTERRUPTED ); 00330 return; 00331 } 00332 00333 ( *instr )->initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err ); 00334 } 00335 00336 // Run each instruction 00337 for( instr = instructions.begin(); instr != instructions.end(); ++instr ) 00338 { 00339 if( MsqInterrupt::interrupt() ) 00340 { 00341 MSQ_SETERR( err )( MsqError::INTERRUPTED ); 00342 return; 00343 } 00344 00345 if( pmesh ) 00346 { 00347 assert( !mesh || pmesh == mesh ); 00348 ( *instr )->loop_over_mesh( pmesh, domain, settings, err ); 00349 } 00350 else 00351 { 00352 ( *instr )->loop_over_mesh( mesh_and_domain, settings, err ); 00353 } 00354 MSQ_ERRRTN( err ); 00355 } 00356 } 00357 00358 void InstructionQueue::clear() 00359 { 00360 instructions.clear(); 00361 autoQualAssess = true; 00362 isMasterSet = false; 00363 masterInstrIndex = 0; 00364 } 00365 00366 std::list< Instruction* >::iterator InstructionQueue::clear_master( MsqError& err ) 00367 { 00368 std::list< Instruction* >::iterator instr_iter; 00369 std::list< Instruction* >::iterator master_pos; 00370 00371 if( !isMasterSet ) 00372 { 00373 MSQ_SETERR( err )( "No master quality improver to clear.", MsqError::INVALID_STATE ); 00374 return instr_iter; 00375 } 00376 00377 // position the instruction iterator over the master quality improver 00378 master_pos = instructions.begin(); 00379 std::advance( master_pos, masterInstrIndex ); 00380 00381 // erases the master quality improver 00382 instr_iter = instructions.erase( master_pos ); 00383 isMasterSet = false; 00384 00385 // returns the position where the Master was 00386 return instr_iter; 00387 }