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 : : // -*- Mode : c++; tab-width: 3; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 3
28 : : // -*-
29 : :
30 : : /*! \file InstructionQueue.cpp
31 : :
32 : : Member functions of the MBMesquite::InstructionQueue class
33 : :
34 : : \author Thomas Leurent
35 : : \date 2002-05-01
36 : : */
37 : :
38 : : #include <string>
39 : : #include <list>
40 : : #include <memory>
41 : :
42 : : #include "InstructionQueue.hpp"
43 : : #include "MsqInterrupt.hpp"
44 : : #include "QualityImprover.hpp"
45 : : #include "QualityAssessor.hpp"
46 : : #include "TargetWriter.hpp"
47 : : #include "VertexSlaver.hpp"
48 : : #include "TagVertexMesh.hpp"
49 : : #include "MsqError.hpp"
50 : : #include "MsqDebug.hpp"
51 : : #include "MsqFPE.hpp"
52 : : #include "ParallelMeshInterface.hpp"
53 : :
54 : : using namespace MBMesquite;
55 : :
56 : 134 : InstructionQueue::InstructionQueue()
57 : : : autoQualAssess( true ), vertexSlaverCount( 0 ), nbPreConditionners( 0 ), isMasterSet( false ),
58 [ + - ]: 134 : masterInstrIndex( 0 )
59 : : {
60 : 134 : }
61 : :
62 [ - + ]: 278 : InstructionQueue::~InstructionQueue() {}
63 : :
64 : 2 : void InstructionQueue::add_target_calculator( TargetWriter* tc, MsqError& )
65 : : {
66 [ + - ]: 2 : instructions.push_back( tc );
67 : 2 : }
68 : :
69 : 1 : void InstructionQueue::add_vertex_slaver( VertexSlaver* vs, MsqError& )
70 : : {
71 [ + - ]: 1 : instructions.push_front( vs );
72 [ + - ]: 1 : if( isMasterSet ) ++masterInstrIndex;
73 : 1 : ++vertexSlaverCount;
74 : 1 : set_slaved_ho_node_mode( Settings::SLAVE_CALCULATED );
75 : 1 : }
76 : :
77 : 1 : void InstructionQueue::remove_vertex_slaver( VertexSlaver* vs, MsqError& err )
78 : : {
79 : 1 : size_t idx = 0;
80 [ # # ][ + - ]: 1 : for( std::list< Instruction* >::iterator i = instructions.begin(); i != instructions.end(); ++i, ++idx )
[ + - ]
81 : : {
82 [ + - ][ + - ]: 1 : if( *i == vs )
83 : : {
84 [ + - ]: 1 : instructions.erase( i );
85 [ + - ][ + - ]: 1 : if( isMasterSet && masterInstrIndex > idx ) --masterInstrIndex;
86 [ + - ][ + - ]: 1 : if( --vertexSlaverCount == 0 ) set_slaved_ho_node_mode( Settings::SLAVE_ALL );
87 : 1 : return;
88 : : }
89 : : }
90 : :
91 [ # # ]: 0 : MSQ_SETERR( err )( "Not found", MsqError::INVALID_ARG );
92 : : }
93 : :
94 : 6 : void InstructionQueue::add_tag_vertex_mesh( TagVertexMesh* vs, MsqError& )
95 : : {
96 [ + - ][ + - ]: 6 : instructions.push_front( vs );
97 [ - + ]: 6 : if( isMasterSet ) ++masterInstrIndex;
98 : 6 : }
99 : :
100 : 0 : void InstructionQueue::remove_tag_vertex_mesh( TagVertexMesh* vs, MsqError& err )
101 : : {
102 : 0 : size_t idx = 0;
103 [ # # ][ # # ]: 0 : for( std::list< Instruction* >::iterator i = instructions.begin(); i != instructions.end(); ++i, ++idx )
[ # # ]
104 : : {
105 [ # # ][ # # ]: 0 : if( *i == vs )
[ # # ]
106 : : {
107 [ # # ]: 0 : instructions.erase( i );
108 [ # # ][ # # ]: 0 : if( isMasterSet && masterInstrIndex > idx ) --masterInstrIndex;
109 : 0 : return;
110 : : }
111 : : }
112 : :
113 [ # # ]: 0 : MSQ_SETERR( err )( "Not found", MsqError::INVALID_ARG );
114 : : }
115 : :
116 : : /*! \fn InstructionQueue::add_preconditioner(QualityImprover* instr, MsqError &err)
117 : : \brief adds a QualityImprover at the end of the instruction list
118 : :
119 : : This function cannot be used once the set_master_quality_improver()
120 : : function has been used.
121 : :
122 : : See also insert_preconditioner().
123 : : */
124 : 1 : void InstructionQueue::add_preconditioner( QualityImprover* instr, MsqError& err )
125 : : {
126 [ - + ]: 1 : if( isMasterSet )
127 : : {
128 : : MSQ_SETERR( err )
129 : : ( "Cannot add preconditioners once the master "
130 : : "QualityImprover has been set.",
131 [ # # ]: 0 : MsqError::INVALID_STATE );
132 : 1 : return;
133 : : }
134 : :
135 [ + - ]: 1 : instructions.push_back( instr );
136 : 1 : nbPreConditionners++;
137 : : }
138 : :
139 : : /*! \fn InstructionQueue::remove_preconditioner(size_t index, MsqError &err)
140 : : \brief removes a QualityImprover* from the instruction queue
141 : :
142 : : \param index is 0-based. An error is set if the index does not correspond
143 : : to a valid element in the queue.
144 : : */
145 : 0 : void InstructionQueue::remove_preconditioner( size_t index, MsqError& err )
146 : : {
147 : : // checks index is valid
148 [ # # ][ # # ]: 0 : if( isMasterSet && index == masterInstrIndex )
149 : : {
150 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "cannot remove master QualityImprover.", MsqError::INVALID_ARG );
151 : 0 : return;
152 : : }
153 [ # # ]: 0 : else if( index >= instructions.size() )
154 : : {
155 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "Index points beyond end of list.", MsqError::INVALID_ARG );
156 : 0 : return;
157 : : }
158 : :
159 : : // position the instruction iterator over the preconditioner to delete
160 [ # # ]: 0 : std::list< Instruction* >::iterator pos;
161 : 0 : pos = instructions.begin();
162 [ # # ]: 0 : std::advance( pos, index );
163 : :
164 [ # # ][ # # ]: 0 : if( !dynamic_cast< QualityImprover* >( *pos ) )
[ # # ][ # # ]
165 : : {
166 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "Index does not point to a QualityImprover.", MsqError::INVALID_ARG );
167 : 0 : return;
168 : : }
169 : :
170 [ # # ][ # # ]: 0 : std::string name = ( *pos )->get_name();
171 [ # # ]: 0 : instructions.erase( pos );
172 : 0 : nbPreConditionners--;
173 : : }
174 : :
175 : : /*! \fn InstructionQueue::insert_preconditioner(QualityImprover* instr, size_t index, MsqError &err)
176 : : \brief inserts a QualityImprover* into the instruction queue.
177 : :
178 : : Pre-conditionners can only be inserted before the master QualityImprover.
179 : :
180 : : \param index is 0-based. An error is set if the index does not correspond
181 : : to a valid position in the queue.
182 : : */
183 : 0 : void InstructionQueue::insert_preconditioner( QualityImprover* instr, size_t index, MsqError& err )
184 : : {
185 : : // checks index is valid
186 [ # # ][ # # ]: 0 : if( isMasterSet == true && index > masterInstrIndex )
187 : : {
188 : : MSQ_SETERR( err )
189 : : ( "Cannot add a preconditioner after the master "
190 : : "QualityImprover.",
191 [ # # ][ # # ]: 0 : MsqError::INVALID_STATE );
192 : 0 : return;
193 : : }
194 [ # # ]: 0 : if( index >= instructions.size() )
195 : : {
196 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "index", MsqError::INVALID_ARG );
197 : 0 : return;
198 : : }
199 : :
200 : : // position the instruction iterator
201 [ # # ]: 0 : std::list< Instruction* >::iterator pos;
202 : 0 : pos = instructions.begin();
203 [ # # ]: 0 : std::advance( pos, index );
204 : : // adds the preconditioner
205 [ # # ]: 0 : instructions.insert( pos, instr );
206 : 0 : nbPreConditionners++;
207 : : }
208 : :
209 : : /*! \fn InstructionQueue::add_quality_assessor(QualityAssessor* instr, MsqError &err)
210 : : \brief adds a QualityAssessor to the instruction queue.
211 : :
212 : : QualityAssessor pointers can be added at any time to the instruction queue.
213 : : */
214 : 118 : void InstructionQueue::add_quality_assessor( QualityAssessor* instr, MsqError& /*err*/ )
215 : : {
216 [ + - ]: 118 : instructions.push_back( instr );
217 : 118 : }
218 : :
219 : : /*! \fn InstructionQueue::remove_quality_assessor(size_t index, MsqError &err)
220 : : \brief removes a QualityAssessor* from the instruction queue
221 : :
222 : : \param index is 0-based. An error is set if the index does not correspond
223 : : to a valid element in the queue.
224 : : */
225 : 1 : void InstructionQueue::remove_quality_assessor( size_t index, MsqError& err )
226 : : {
227 : : // checks index is valid
228 [ - + ]: 1 : if( index >= instructions.size() )
229 : : {
230 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "index", MsqError::INVALID_ARG );
231 : 1 : return;
232 : : }
233 : :
234 : : // position the instruction iterator over the QualityAssessor to delete
235 [ + - ]: 1 : std::list< Instruction* >::iterator pos;
236 : 1 : pos = instructions.begin();
237 [ + - ]: 1 : std::advance( pos, index );
238 : :
239 [ + - ][ + - ]: 1 : if( !dynamic_cast< QualityAssessor* >( *pos ) )
[ - + ][ - + ]
240 : : {
241 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "Index does not point to a QualityImprover.", MsqError::INVALID_ARG );
242 : 0 : return;
243 : : }
244 : :
245 [ + - ][ + - ]: 1 : std::string name = ( *pos )->get_name();
246 [ + - ]: 1 : instructions.erase( pos );
247 : : }
248 : :
249 : : /*! \fn InstructionQueue::insert_quality_assessor(QualityAssessor* instr, size_t index, MsqError
250 : : &err) \brief inserts a QualityAssessor* into the instruction queue.
251 : :
252 : : QualityAssessors can be inserted at any position in the instruction queue.
253 : :
254 : : \param index is 0-based. An error is set if the index is past the end of the queue.
255 : : */
256 : 0 : void InstructionQueue::insert_quality_assessor( QualityAssessor* instr, size_t index, MsqError& err )
257 : : {
258 : : // checks index is valid
259 [ # # ]: 0 : if( index > instructions.size() )
260 : : {
261 : : MSQ_SETERR( err )
262 [ # # ][ # # ]: 0 : ( "index points two positions beyond end of list.", MsqError::INVALID_ARG );
263 : 0 : return;
264 : : }
265 : :
266 : : // position the instruction iterator
267 [ # # ]: 0 : std::list< Instruction* >::iterator pos;
268 : 0 : pos = instructions.begin();
269 [ # # ]: 0 : std::advance( pos, index );
270 : : // adds the QualityAssessor
271 [ # # ]: 0 : instructions.insert( pos, instr );
272 : : }
273 : :
274 : 126 : void InstructionQueue::set_master_quality_improver( QualityImprover* instr, MsqError& err )
275 : : {
276 [ - + ]: 126 : if( isMasterSet )
277 : : {
278 : : MSQ_DBGOUT( 1 ) << "InstructionQueue::set_master_quality_improver():\n"
279 : : << "\tOverwriting previously specified master quality improver.\n";
280 : : // if master is already set, clears it and insert the new one at the same position.
281 [ # # ]: 0 : std::list< Instruction* >::iterator master_pos;
282 [ # # ][ # # ]: 126 : master_pos = this->clear_master( err );MSQ_ERRRTN( err );
[ # # ][ # # ]
[ # # ][ # # ]
283 [ # # ]: 0 : instructions.insert( master_pos, instr );
284 : 0 : isMasterSet = true;
285 : : }
286 : : else
287 : : {
288 : : // if master is not set, add it at the end of the queue.
289 [ + - ]: 126 : instructions.push_back( instr );
290 : 126 : isMasterSet = true;
291 : 126 : masterInstrIndex = instructions.size() - 1;
292 : : }
293 : : }
294 : :
295 : 276 : void InstructionQueue::run_common( MeshDomainAssoc* mesh_and_domain, ParallelMesh* pmesh, Settings* settings,
296 : : MsqError& err )
297 : : {
298 : : MSQ_DBGOUT( 1 ) << version_string( false ) << "\n";
299 : :
300 [ + + ][ - + ]: 138 : if( nbPreConditionners != 0 && isMasterSet == false )
301 : : {
302 : : MSQ_SETERR( err )
303 : : ( "no pre-conditionners allowed if master QualityImprover "
304 : : "is not set.",
305 [ # # ][ # # ]: 0 : MsqError::INVALID_STATE );
306 : 138 : return;
307 : : }
308 : :
309 : : #ifdef ENABLE_INTERRUPT
310 : : // Register SIGINT handler
311 : : MsqInterrupt msq_interrupt;
312 : : #endif
313 : :
314 [ + - ]: 138 : Mesh* mesh = mesh_and_domain->get_mesh();
315 [ + - ]: 138 : MeshDomain* domain = mesh_and_domain->get_domain();
316 : :
317 : : // Generate SIGFPE on floating point errors
318 [ + - ][ + - ]: 138 : MsqFPE fpe_trap( settings->trap_floating_point_exception() );
319 : :
320 [ + - ]: 138 : std::list< Instruction* >::const_iterator instr;
321 : :
322 : : // Initialize each instruction
323 [ + - ][ + - ]: 398 : for( instr = instructions.begin(); instr != instructions.end(); ++instr )
[ + - ][ + - ]
[ + + ]
324 : : {
325 [ + - ][ - + ]: 260 : if( MsqInterrupt::interrupt() )
326 : : {
327 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( MsqError::INTERRUPTED );
328 : 0 : return;
329 : : }
330 : :
331 [ + - ][ + - ]: 260 : ( *instr )->initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
[ + - ][ - + ]
[ # # ][ # # ]
[ - + ]
332 : : }
333 : :
334 : : // Run each instruction
335 [ + - ][ + - ]: 398 : for( instr = instructions.begin(); instr != instructions.end(); ++instr )
[ + - ][ + - ]
[ + + ][ + + ]
336 : : {
337 [ + - ][ - + ]: 260 : if( MsqInterrupt::interrupt() )
338 : : {
339 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( MsqError::INTERRUPTED );
340 : 0 : return;
341 : : }
342 : :
343 [ - + ]: 260 : if( pmesh )
344 : : {
345 [ # # ][ # # ]: 0 : assert( !mesh || pmesh == mesh );
[ # # ]
346 [ # # ][ # # ]: 0 : ( *instr )->loop_over_mesh( pmesh, domain, settings, err );
347 : : }
348 : : else
349 : : {
350 [ + - ][ + - ]: 260 : ( *instr )->loop_over_mesh( mesh_and_domain, settings, err );
351 : : }
352 [ + - ][ + + ]: 260 : MSQ_ERRRTN( err );
[ + - ][ + - ]
[ + + ]
353 : 136 : }
354 : : }
355 : :
356 : 0 : void InstructionQueue::clear()
357 : : {
358 : 0 : instructions.clear();
359 : 0 : autoQualAssess = true;
360 : 0 : isMasterSet = false;
361 : 0 : masterInstrIndex = 0;
362 : 0 : }
363 : :
364 : 0 : std::list< Instruction* >::iterator InstructionQueue::clear_master( MsqError& err )
365 : : {
366 [ # # ]: 0 : std::list< Instruction* >::iterator instr_iter;
367 [ # # ]: 0 : std::list< Instruction* >::iterator master_pos;
368 : :
369 [ # # ]: 0 : if( !isMasterSet )
370 : : {
371 [ # # ][ # # ]: 0 : MSQ_SETERR( err )( "No master quality improver to clear.", MsqError::INVALID_STATE );
372 : 0 : return instr_iter;
373 : : }
374 : :
375 : : // position the instruction iterator over the master quality improver
376 : 0 : master_pos = instructions.begin();
377 [ # # ]: 0 : std::advance( master_pos, masterInstrIndex );
378 : :
379 : : // erases the master quality improver
380 [ # # ]: 0 : instr_iter = instructions.erase( master_pos );
381 : 0 : isMasterSet = false;
382 : :
383 : : // returns the position where the Master was
384 : 0 : return instr_iter;
385 [ + - ][ + - ]: 120 : }
|