MOAB: Mesh Oriented datABase  (version 5.2.1)
InstructionQueue.cpp
Go to the documentation of this file.
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     diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
00024     pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
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, ParallelMesh* pmesh, Settings* settings,
00296                                    MsqError& err )
00297 {
00298     MSQ_DBGOUT( 1 ) << version_string( false ) << "\n";
00299 
00300     if( nbPreConditionners != 0 && isMasterSet == false )
00301     {
00302         MSQ_SETERR( err )
00303         ( "no pre-conditionners allowed if master QualityImprover "
00304           "is not set.",
00305           MsqError::INVALID_STATE );
00306         return;
00307     }
00308 
00309 #ifdef ENABLE_INTERRUPT
00310     // Register SIGINT handler
00311     MsqInterrupt msq_interrupt;
00312 #endif
00313 
00314     Mesh* mesh         = mesh_and_domain->get_mesh();
00315     MeshDomain* domain = mesh_and_domain->get_domain();
00316 
00317     // Generate SIGFPE on floating point errors
00318     MsqFPE fpe_trap( settings->trap_floating_point_exception() );
00319 
00320     std::list< Instruction* >::const_iterator instr;
00321 
00322     // Initialize each instruction
00323     for( instr = instructions.begin(); instr != instructions.end(); ++instr )
00324     {
00325         if( MsqInterrupt::interrupt() )
00326         {
00327             MSQ_SETERR( err )( MsqError::INTERRUPTED );
00328             return;
00329         }
00330 
00331         ( *instr )->initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
00332     }
00333 
00334     // Run each instruction
00335     for( instr = instructions.begin(); instr != instructions.end(); ++instr )
00336     {
00337         if( MsqInterrupt::interrupt() )
00338         {
00339             MSQ_SETERR( err )( MsqError::INTERRUPTED );
00340             return;
00341         }
00342 
00343         if( pmesh )
00344         {
00345             assert( !mesh || pmesh == mesh );
00346             ( *instr )->loop_over_mesh( pmesh, domain, settings, err );
00347         }
00348         else
00349         {
00350             ( *instr )->loop_over_mesh( mesh_and_domain, settings, err );
00351         }
00352         MSQ_ERRRTN( err );
00353     }
00354 }
00355 
00356 void InstructionQueue::clear()
00357 {
00358     instructions.clear();
00359     autoQualAssess   = true;
00360     isMasterSet      = false;
00361     masterInstrIndex = 0;
00362 }
00363 
00364 std::list< Instruction* >::iterator InstructionQueue::clear_master( MsqError& err )
00365 {
00366     std::list< Instruction* >::iterator instr_iter;
00367     std::list< Instruction* >::iterator master_pos;
00368 
00369     if( !isMasterSet )
00370     {
00371         MSQ_SETERR( err )( "No master quality improver to clear.", MsqError::INVALID_STATE );
00372         return instr_iter;
00373     }
00374 
00375     // position the instruction iterator over the master quality improver
00376     master_pos = instructions.begin();
00377     std::advance( master_pos, masterInstrIndex );
00378 
00379     // erases the master quality improver
00380     instr_iter  = instructions.erase( master_pos );
00381     isMasterSet = false;
00382 
00383     // returns the position where the Master was
00384     return instr_iter;
00385 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines