MOAB: Mesh Oriented datABase  (version 5.4.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     [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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines