Branch data Line data Source code
1 : : /** \file ScdInterface.hpp
2 : : */
3 : : #ifndef SCD_INTERFACE
4 : : #define SCD_INTERFACE
5 : :
6 : : #include "moab/Interface.hpp"
7 : : #include "moab/HomXform.hpp"
8 : :
9 : : #include <iostream>
10 : : #include <vector>
11 : : #include "assert.h"
12 : :
13 : : #include "moab/win32_config.h"
14 : :
15 : : namespace moab
16 : : {
17 : :
18 : : class StructuredElementSeq;
19 : : class EntitySequence;
20 : : class ScdVertexData;
21 : : class EntitySequence;
22 : : class ScdBox;
23 : : class ParallelComm;
24 : :
25 : : /** \class ScdInterface ScdInterface.hpp "moab/ScdInterface.hpp"
26 : : * \brief A structured mesh interface for MOAB-based data
27 : : *
28 : : * Structured mesh in MOAB is created and accessed through the ScdInterface and ScdBox classes.
29 : : *
30 : : * \section Construction Construction and Representation
31 : : * Structured mesh can be constructed in one of two ways. First, a rectangular block of mesh,
32 : : * both vertices and edges/quads/hexes, can be created in one shot, using the construct_box method.
33 : : * In this case, there are single sequences of vertices/entities. The second method for creating
34 : : * structured mesh is to create the structured blocks of vertices and elements separately. In
35 : : * this case, different blocks of elements can share blocks of vertices, and each block of
36 : : * elements has its own independent parametric space. The algorithms behind this representation
37 : : * are described in T. Tautges, "MOAB-SD: Integrated structured and unstructured mesh
38 : : * representation", Eng. w Comp, vol 20 no. 3.
39 : : *
40 : : * Structured mesh is represented in MOAB down at the element sequence level, which is something
41 : : * applications don't see. In addition, when structured mesh is created, entity sets are also
42 : : * created and tagged with information about the parametric space. In particular, the BOX_DIMS
43 : : * tag is used to indicate the lower and upper corners in parametric space (this
44 : : * tag is integer size 6). Structured mesh blocks are also available through ScdBox class objects
45 : : * returned by ScdInterface. These class objects should be treated only as references to the
46 : : * structured mesh blocks; that is, the structured mesh referenced by these objects is not deleted
47 : : * when the ScdBox instance is destroyed. Functions for destroying the actual mesh are available
48 : : * on this class, though.
49 : : *
50 : : * Structured mesh blocks are returned in the form of ScdBox class objects. Each ScdBox instance
51 : : * represents a rectangular block of vertices and possibly elements (edges, quads, or hexes). The
52 : : * edge/quad/hex entity handles for a ScdBox are guaranteed to be contiguous, starting at a starting
53 : : * value which is also available through the ScdBox class. However, vertex handles may or may not
54 : : * be contiguous, depending on the construction method. The start vertex handle is also available
55 : : * from the ScdBox class.
56 : : *
57 : : * \section Parameters Parametric Space
58 : : *
59 : : * Each structured box has a parametric (ijk) space, which can be queried through the ScdBox
60 : : * interface. For non-periodic boxes, the edge/quad/hex parameter bounds are one less in each
61 : : * dimension than that of the vertices, otherwise they are the same as the vertex parameter bounds.
62 : : * In a parallel representation, boxes are locally non-periodic by default, but global ids are
63 : : * assigned such that the last set of vertices in a periodic direction match those of the first set
64 : : * of vertices in that direction.
65 : : *
66 : : * Entity handles are allocated with the i parameter varying fastest, then j, then k.
67 : : *
68 : : * \section Per Periodic Meshes
69 : : * Boxes can be periodic in i, or j, or both i and j. If only i or j is periodic, the corresponding
70 : : * mesh is a strip or an annular cylinder; if both i and j are periodic, the corresponding mesh is
71 : : * an annular torus. A box cannot be periodic in all three parameters. If i and/or j is periodic,
72 : : * and assuming IMIN/JMIN is zero, the parameter extents in the/each periodic direction (IMAX/JMAX)
73 : : * for vertices and edges/faces/hexes are the same, and the vertices on the "top" end in the
74 : : * periodic direction are at parameter value IMIN/JMIN.
75 : : *
76 : : * \section Par Parallel Representation
77 : : *
78 : : * For parallel structured meshes, each local mesh (the mesh on a given process) looks like a
79 : : * non-periodic structured mesh, and there are both local and global parameters of the structured
80 : : * mesh. If the mesh is periodic in a given direction, the last process in the periodic direction
81 : : * has local IMAX/JMAX that is one greater than the global IMAX/JMAX.
82 : : *
83 : : *
84 : : * In parallel, the periodicity described in the previous paragraph is "local periodicity"; there is
85 : : * also the notion of global periodicity. For serial meshes, those concepts are the same. In
86 : : * parallel, a mesh can be locally non-periodic but globally periodic in a given direction. In that
87 : : * case, the local mesh is still non-periodic, i.e. the parametric extents for edges is one fewer
88 : : * than that of vertices in that direction. However, vertices are given global ids such that they
89 : : * match those of the parametric minimum in that direction. Geometric positions of the vertices at
90 : : * the high end should still be greater than the ones just below.
91 : : *
92 : : * \section Adjs Adjacent Entities
93 : : * This interface supports parametric access to intermediate-dimension entities, e.g. adjacent faces
94 : : * and edges in a 3d mesh. In this case, a direction parameter is added, to identify the parametric
95 : : * direction of the entities being requested. For example, to retrieve the faces adjacent to a hex
96 : : * with parameters ijk, in the i parametric direction, you would use the parameters ijk0. These
97 : : * intermediate entities are not stored in a structured representation, but their parametric
98 : : * positions can be evaluated based on their adjacencies to higher-dimensional entities. Thanks to
99 : : * Milad Fatenejad for the thinking behind this.
100 : : *
101 : : * \section Evaluation Evaluation
102 : : * The ScdBox class provides functions for evaluating the mesh based on the ijk parameter space.
103 : : * These functions are inlined where possible, for efficiency.
104 : : */
105 : :
106 : : //! struct for keeping parallel data in one place
107 : : class ScdParData
108 : : {
109 : : public:
110 : 58 : ScdParData() : partMethod( NOPART ), pComm( NULL )
111 : : {
112 : 58 : gDims[0] = gDims[1] = gDims[2] = gDims[3] = gDims[4] = gDims[5] = 0;
113 : 58 : gPeriodic[0] = gPeriodic[1] = gPeriodic[2] = 0;
114 : 58 : pDims[0] = pDims[1] = pDims[2] = 0;
115 : 58 : }
116 : :
117 : : //! Partition method enumeration; these strategies are described in comments for
118 : : //! compute_partition_alljorkori, compute_partition_alljkbal, compute_partition_sqij,
119 : : //! compute_partition_sqjk, and compute_partition_sqijk
120 : : enum PartitionMethod
121 : : {
122 : : ALLJORKORI = 0,
123 : : ALLJKBAL,
124 : : SQIJ,
125 : : SQJK,
126 : : SQIJK,
127 : : TRIVIAL,
128 : : RCBZOLTAN,
129 : : NOPART
130 : : };
131 : :
132 : : //! Partition method names
133 : : static MOAB_EXPORT const char* PartitionMethodNames[NOPART + 1];
134 : :
135 : : //! partition method used to partition global parametric space
136 : : int partMethod;
137 : :
138 : : //! lower and upper corners of global box
139 : : int gDims[6];
140 : :
141 : : //! is globally periodic in i or j or k
142 : : int gPeriodic[3];
143 : :
144 : : //! number of procs in each direction
145 : : int pDims[3];
146 : :
147 : : //! parallel communicator object for this par scd mesh
148 : : ParallelComm* pComm;
149 : : };
150 : :
151 : : class ScdInterface
152 : : {
153 : : public:
154 : : friend class ScdBox;
155 : :
156 : : //! Constructor
157 : : /** Constructor; if find_boxes is true, this will search for entity sets marked as
158 : : * structured blocks, based on the BOX_DIMS tag. Structured mesh blocks will be stored
159 : : * in this interface class for future retrieval. Structured mesh blocks created through
160 : : * this interface will also be stored here.
161 : : * \param impl MOAB instance
162 : : * \param find_boxes If true, search all the entity sets, caching the structured mesh blocks
163 : : */
164 : : ScdInterface( Interface* impl, bool find_boxes = false );
165 : :
166 : : // Destructor
167 : : ~ScdInterface();
168 : :
169 : : //! Return the MOAB Interface instance *
170 : : Interface* impl() const;
171 : :
172 : : //! Construct new structured mesh box, including both vertices and elements
173 : : /** Parameter range
174 : : * for vertex box is [low-high], for elements is [low-high). Construct quads by passing
175 : : * in low[2] == high[2], and edges by passing in low[1] == high[1] and low[2] == high[2].
176 : : * The result is passed back in a ScdBox*, which is a *reference* to the box of structured mesh.
177 : : * That is, the actual mesh is retained in MOAB when the ScdBox is destroyed. To actually
178 : : * destroy the mesh, call the destroy_mesh function on the ScdBox object first, before
179 : : * destroying it. \param low Lower corner in parameter space \param high Higher corner in
180 : : * parameter space \param coords Coordinates of vertices, interleaved (xyzxyz...); if NULL,
181 : : * coords are set to parametric values \param num_coords Number of coordinate values \param
182 : : * new_box Reference to box of structured mesh \param lperiodic[3] If lperiodic[s] != 0,
183 : : * direction s is locally periodic \param par_data If non-NULL, this will get stored on the
184 : : * ScdBox once created, contains info about global parallel nature of ScdBox across procs \param
185 : : * assign_global_ids If true, assigns 1-based global ids to vertices using GLOBAL_ID_TAG_NAME
186 : : * \param resolve_shared_ents If != -1, resolves shared entities up to and including dimension
187 : : * equal to value
188 : : */
189 : : ErrorCode construct_box( HomCoord low, HomCoord high, const double* const coords, unsigned int num_coords,
190 : : ScdBox*& new_box, int* const lperiodic = NULL, ScdParData* const par_data = NULL,
191 : : bool assign_global_ids = false, int resolve_shared_ents = -1 );
192 : :
193 : : //! Create a structured sequence of vertices, quads, or hexes
194 : : /** Starting handle for the sequence is available from the returned ScdBox.
195 : : * If creating a structured quad or hex box, subsequent calls must be made to ScdBox::add_vbox,
196 : : * until all the vertices have been filled in for the box.
197 : : * \param low Lower corner of structured box
198 : : * \param high Higher corner of structured box
199 : : * \param type EntityType, one of MBVERTEX, MBEDGE, MBQUAD, MBHEX
200 : : * \param starting_id Requested start id of entities
201 : : * \param new_box Reference to the newly created box of entities
202 : : * \param is_periodic[3] If is_periodic[s] is non-zero, mesh should be periodic in direction s
203 : : * (s=[0,1,2])
204 : : */
205 : : ErrorCode create_scd_sequence( const HomCoord& low, const HomCoord& high, EntityType type, int starting_id,
206 : : ScdBox*& new_box, int* is_periodic = NULL );
207 : :
208 : : //! Return all the structured mesh blocks in this MOAB instance, as ScdBox objects
209 : : /** Return the structured blocks in this MOAB instance. If these were not searched for
210 : : * at instantiation time, then the search is done now.
211 : : * \param boxes Vector of ScdBox objects representing structured mesh blocks
212 : : */
213 : : ErrorCode find_boxes( std::vector< ScdBox* >& boxes );
214 : :
215 : : //! Return all the structured mesh blocks in this MOAB instance, as entity set handles
216 : : /** Return the structured blocks in this MOAB instance. If these were not searched for
217 : : * at instantiation time, then the search is done now.
218 : : * \param boxes Range of entity set objects representing structured mesh blocks
219 : : */
220 : : ErrorCode find_boxes( Range& boxes );
221 : :
222 : : //! Return all the structured mesh blocks known by ScdInterface (does not search)
223 : : /** Return the structured blocks in this ScdInterface instance. Does not search for new boxes,
224 : : * just returns the contents of the list.
225 : : * \param boxes Structured boxes
226 : : */
227 : : ErrorCode get_boxes( std::vector< ScdBox* >& boxes );
228 : :
229 : : //! Return the tag marking the lower and upper corners of boxes
230 : : /**
231 : : * \param create_if_missing If the tag does not yet exist, create it
232 : : */
233 : : Tag box_dims_tag( bool create_if_missing = true );
234 : :
235 : : //! Return the tag marking the global lower and upper corners of boxes
236 : : /**
237 : : * \param create_if_missing If the tag does not yet exist, create it
238 : : */
239 : : Tag global_box_dims_tag( bool create_if_missing = true );
240 : :
241 : : //! Return the tag marking the partitioning method used to partition the box in parallel
242 : : /**
243 : : * \param create_if_missing If the tag does not yet exist, create it
244 : : */
245 : : Tag part_method_tag( bool create_if_missing = true );
246 : :
247 : : //! Return the tag marking whether box is periodic in i and j
248 : : /**
249 : : * \param create_if_missing If the tag does not yet exist, create it
250 : : */
251 : : Tag box_periodic_tag( bool create_if_missing = true );
252 : :
253 : : //! Return the tag marking the ScdBox for a set
254 : : /**
255 : : * \param create_if_missing If the tag does not yet exist, create it
256 : : */
257 : : Tag box_set_tag( bool create_if_missing = true );
258 : :
259 : : //! Return the ScdBox corresponding to the entity set passed in
260 : : /** If the entity isn't a structured box set, NULL is returned.
261 : : * \param eh Entity whose box is being queried
262 : : */
263 : : ScdBox* get_scd_box( EntityHandle eh );
264 : :
265 : : //! Compute a partition of structured parameter space
266 : : /** Compute a partition of structured parameter space, based on data in the ScdParData
267 : : * passed in. Results are passed back in arguments, which application can set back into
268 : : * par_data argument if they so desire.
269 : : * \param np Number of processors
270 : : * \param nr Rank of this processor
271 : : * \param par_data ScdParData object that contains input global parameter space, desired
272 : : * partitioning method, and information about global periodicity.
273 : : * \param ldims Local parameters for grid
274 : : * \param lperiodic Whether or not a given dimension is locally periodic
275 : : * \param pdims Number of procs in i, j, k directions
276 : : */
277 : : static ErrorCode compute_partition( int np, int nr, const ScdParData& par_data, int* ldims, int* lperiodic = NULL,
278 : : int* pdims = NULL );
279 : :
280 : : //! Get information about the neighbor in the dijk[] direction, where dijk can be -1 or 1 for
281 : : //! all 3 params
282 : : /** Get information about the neighbor in the dijk[] direction, where dijk can be -1 or 1 for
283 : : * all 3 params \param np (in) Total # procs \param nr Processor from which neighbor is
284 : : * requested \param spd (in) ScdParData containing part method, gdims, gperiodic data \param
285 : : * dijk(*) (in) Direction being queried, = +/-1 or 0 \param pto (out) Processor holding the
286 : : * destination part \param rdims(6) (out) Parametric min/max of destination part \param
287 : : * facedims(6) (out) Parametric min/max of interface between pfrom and pto; if at the max in a
288 : : * periodic direction, set to global min of that direction \param across_bdy(3) (out) If
289 : : * across_bdy[i] is -1(1), interface with pto is across periodic lower(upper) bdy in parameter
290 : : * i, 0 otherwise
291 : : */
292 : : static ErrorCode get_neighbor( int np, int nr, const ScdParData& spd, const int* const dijk, int& pto, int* rdims,
293 : : int* facedims, int* across_bdy );
294 : :
295 : : //! Tag vertices with sharing data for parallel representations
296 : : /** Given the ParallelComm object to use, tag the vertices shared with other processors
297 : : */
298 : : ErrorCode tag_shared_vertices( ParallelComm* pcomm, EntityHandle seth );
299 : :
300 : : //! Tag vertices with sharing data for parallel representations
301 : : /** Given the ParallelComm object to use, tag the vertices shared with other processors
302 : : */
303 : : ErrorCode tag_shared_vertices( ParallelComm* pcomm, ScdBox* box );
304 : :
305 : : protected:
306 : : //! Remove the box from the list on ScdInterface
307 : : ErrorCode remove_box( ScdBox* box );
308 : :
309 : : //! Add the box to the list on ScdInterface
310 : : ErrorCode add_box( ScdBox* box );
311 : :
312 : : private:
313 : : //! Create an entity set for a box, and tag with the parameters
314 : : /** \param low Lower corner parameters for this box
315 : : * \param high Upper corner parameters for this box
316 : : * \param scd_set Entity set created
317 : : * \param is_periodic[3] If is_periodic[s] is non-zero, mesh should be periodic in direction s
318 : : * (s=[0,1,2])
319 : : */
320 : : ErrorCode create_box_set( const HomCoord& low, const HomCoord& high, EntityHandle& scd_set,
321 : : int* is_periodic = NULL );
322 : :
323 : : //! Compute a partition of structured parameter space
324 : : /** Partitions the structured parametric space by partitioning j, k, or i only.
325 : : * If j is greater than #procs, partition that, else k, else i.
326 : : * For description of arguments, see ScdInterface::compute_partition.
327 : : */
328 : : inline static ErrorCode compute_partition_alljorkori( int np, int nr, const int gijk[6], const int* const gperiodic,
329 : : int* lijk, int* lperiodic, int* pijk );
330 : :
331 : : //! Compute a partition of structured parameter space
332 : : /** Partitions the structured parametric space by partitioning j, and possibly k,
333 : : * seeking square regions of jk space
334 : : * For description of arguments, see ScdInterface::compute_partition.
335 : : */
336 : : inline static ErrorCode compute_partition_alljkbal( int np, int nr, const int gijk[6], const int* const gperiodic,
337 : : int* lijk, int* lperiodic, int* pijk );
338 : :
339 : : //! Compute a partition of structured parameter space
340 : : /** Partitions the structured parametric space by seeking square ij partitions
341 : : * For description of arguments, see ScdInterface::compute_partition.
342 : : */
343 : : inline static ErrorCode compute_partition_sqij( int np, int nr, const int gijk[6], const int* const gperiodic,
344 : : int* lijk, int* lperiodic, int* pijk );
345 : :
346 : : //! Compute a partition of structured parameter space
347 : : /** Partitions the structured parametric space by seeking square jk partitions
348 : : * For description of arguments, see ScdInterface::compute_partition.
349 : : */
350 : : inline static ErrorCode compute_partition_sqjk( int np, int nr, const int gijk[6], const int* const gperiodic,
351 : : int* lijk, int* lperiodic, int* pijk );
352 : :
353 : : //! Compute a partition of structured parameter space
354 : : /** Partitions the structured parametric space by seeking square ijk partitions
355 : : * For description of arguments, see ScdInterface::compute_partition.
356 : : */
357 : : inline static ErrorCode compute_partition_sqijk( int np, int nr, const int gijk[6], const int* const gperiodic,
358 : : int* lijk, int* lperiodic, int* pijk );
359 : :
360 : : //! Get vertices shared with other processors
361 : : /** Shared vertices returned as indices into each proc's handle space
362 : : * \param box Box used to get parametric space info
363 : : * \param procs Procs this proc shares vertices with
364 : : * \param offsets Offsets into indices list for each proc
365 : : * \param shared_indices local/remote indices of shared vertices
366 : : */
367 : : static ErrorCode get_shared_vertices( ParallelComm* pcomm, ScdBox* box, std::vector< int >& procs,
368 : : std::vector< int >& offsets, std::vector< int >& shared_indices );
369 : :
370 : : static ErrorCode get_indices( const int* const ldims, const int* const rdims, const int* const across_bdy,
371 : : int* face_dims, std::vector< int >& shared_indices );
372 : :
373 : : static ErrorCode get_neighbor_alljorkori( int np, int pfrom, const int* const gdims, const int* const gperiodic,
374 : : const int* const dijk, int& pto, int* rdims, int* facedims,
375 : : int* across_bdy );
376 : :
377 : : static ErrorCode get_neighbor_alljkbal( int np, int pfrom, const int* const gdims, const int* const gperiodic,
378 : : const int* const dijk, int& pto, int* rdims, int* facedims,
379 : : int* across_bdy );
380 : :
381 : : static ErrorCode get_neighbor_sqij( int np, int pfrom, const int* const gdims, const int* const gperiodic,
382 : : const int* const dijk, int& pto, int* rdims, int* facedims, int* across_bdy );
383 : :
384 : : static ErrorCode get_neighbor_sqjk( int np, int pfrom, const int* const gdims, const int* const gperiodic,
385 : : const int* const dijk, int& pto, int* rdims, int* facedims, int* across_bdy );
386 : :
387 : : static ErrorCode get_neighbor_sqijk( int np, int pfrom, const int* const gdims, const int* const gperiodic,
388 : : const int* const dijk, int& pto, int* rdims, int* facedims, int* across_bdy );
389 : :
390 : : static int gtol( const int* gijk, int i, int j, int k );
391 : :
392 : : //! assign global ids to vertices in this box
393 : : ErrorCode assign_global_ids( ScdBox* box );
394 : :
395 : : //! interface instance
396 : : Interface* mbImpl;
397 : :
398 : : //! whether we've searched the database for boxes yet
399 : : bool searchedBoxes;
400 : :
401 : : //! structured mesh blocks; stored as ScdBox objects, can get sets from those
402 : : std::vector< ScdBox* > scdBoxes;
403 : :
404 : : //! tag representing whether box is periodic in i and j
405 : : Tag boxPeriodicTag;
406 : :
407 : : //! tag representing box lower and upper corners
408 : : Tag boxDimsTag;
409 : :
410 : : //! tag representing global lower and upper corners
411 : : Tag globalBoxDimsTag;
412 : :
413 : : //! tag representing partition method
414 : : Tag partMethodTag;
415 : :
416 : : //! tag pointing from set to ScdBox
417 : : Tag boxSetTag;
418 : : };
419 : :
420 : : class ScdBox
421 : : {
422 : : friend class ScdInterface;
423 : :
424 : : public:
425 : : //! Destructor
426 : : ~ScdBox();
427 : :
428 : : //! Return the ScdInterface responsible for this box
429 : : inline ScdInterface* sc_impl() const;
430 : :
431 : : //! Add a vertex box to this box
432 : : /* Add a vertex box to the element sequence referenced by this box. The passed in vbox must
433 : : * be a vertex box, with parametric extents no larger than that of this box. This vbox is
434 : : * oriented to this box by matching parameters from1-from3 in vbox to to1-to3 in this box.
435 : : * If bb_input is true, only the part of the vertex sequence between bb_min and bb_max is
436 : : * referenced \param vbox The vertex box being added to this box \param from1 1st reference
437 : : * point on vbox \param to1 1st reference point on this box \param from2 2nd reference point on
438 : : * vbox \param to2 2nd reference point on this box \param from3 3rd reference point on vbox
439 : : * \param to3 3rd reference point on this box
440 : : * \param bb_input If true, subsequent parameters list extents of vbox referenced
441 : : * \param bb_min Lower corner of rectangle referenced
442 : : * \param bb_max Upper corner of rectangle referenced
443 : : */
444 : : ErrorCode add_vbox( ScdBox* vbox, HomCoord from1, HomCoord to1, HomCoord from2, HomCoord to2, HomCoord from3,
445 [ + - ][ + - ]: 28 : HomCoord to3, bool bb_input = false, const HomCoord& bb_min = HomCoord::getUnitv( 0 ),
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
446 [ + - ][ + - ]: 28 : const HomCoord& bb_max = HomCoord::getUnitv( 0 ) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
447 : : // const HomCoord &bb_min = HomCoord::unitv[0],
448 : : // const HomCoord &bb_max = HomCoord::unitv[0]);
449 : :
450 : : //! Return whether this box has all its vertices defined
451 : : /** Tests whether vertex boxs added with add_vbox have completely defined the vertex parametric
452 : : * space for this box.
453 : : *
454 : : */
455 : : bool boundary_complete() const;
456 : :
457 : : //! Return highest topological dimension of box
458 : : inline int box_dimension() const;
459 : :
460 : : //! Starting vertex handle for this box
461 : : inline EntityHandle start_vertex() const;
462 : :
463 : : //! Starting entity handle for this box
464 : : /** If this is a vertex box, the start vertex handle is returned.
465 : : */
466 : : inline EntityHandle start_element() const;
467 : :
468 : : //! Return the number of elements in the box
469 : : /* Number of elements is (boxSize[0]-1)(boxSize[1]-1)(boxSize[2]-1)
470 : : */
471 : : inline int num_elements() const;
472 : :
473 : : //! Return the number of vertices in the box
474 : : /* Number of vertices is boxSize[0] * boxSize[1] * boxSize[2]
475 : : */
476 : : inline int num_vertices() const;
477 : :
478 : : //! Return the parametric coordinates for this box
479 : : /**
480 : : * \return IJK parameters of lower and upper corners
481 : : */
482 : : inline const int* box_dims() const;
483 : :
484 : : //! Return the lower corner parametric coordinates for this box
485 : : inline HomCoord box_min() const;
486 : :
487 : : //! Return the upper corner parametric coordinates for this box
488 : : inline HomCoord box_max() const;
489 : :
490 : : //! Return the parameter extents for this box
491 : : inline HomCoord box_size() const;
492 : :
493 : : //! Return the parametric extents for this box
494 : : /**
495 : : * \param ijk IJK extents of this box
496 : : */
497 : : inline void box_size( int* ijk ) const;
498 : :
499 : : //! Return the parametric extents for this box
500 : : /**
501 : : * \param i I extent of this box
502 : : * \param j J extent of this box
503 : : * \param k K extent of this box
504 : : */
505 : : void box_size( int& i, int& j, int& k ) const;
506 : :
507 : : //! Get the element at the specified coordinates
508 : : /**
509 : : * \param ijk Parametric coordinates being evaluated
510 : : */
511 : : EntityHandle get_element( const HomCoord& ijk ) const;
512 : :
513 : : //! Get the element at the specified coordinates
514 : : /**
515 : : * \param i Parametric coordinates being evaluated
516 : : * \param j Parametric coordinates being evaluated
517 : : * \param k Parametric coordinates being evaluated
518 : : */
519 : : EntityHandle get_element( int i, int j = 0, int k = 0 ) const;
520 : :
521 : : //! Get the vertex at the specified coordinates
522 : : /**
523 : : * \param ijk Parametric coordinates being evaluated
524 : : */
525 : : EntityHandle get_vertex( const HomCoord& ijk ) const;
526 : :
527 : : //! Get the vertex at the specified coordinates
528 : : /**
529 : : * \param i Parametric coordinates being evaluated
530 : : * \param j Parametric coordinates being evaluated
531 : : * \param k Parametric coordinates being evaluated
532 : : */
533 : : EntityHandle get_vertex( int i, int j = 0, int k = 0 ) const;
534 : :
535 : : //! Get parametric coordinates of the specified entity
536 : : /** This function returns MB_ENTITY_NOT_FOUND if the entity is not
537 : : * in this ScdBox.
538 : : * \param ent Entity being queried
539 : : * \param i Parametric coordinates returned
540 : : * \param j Parametric coordinates returned
541 : : * \param k Parametric coordinates returned
542 : : * \param dir Parametric coordinate direction returned (in case of getting adjacent
543 : : * edges (2d, 3d) or faces (3d); not modified otherwise
544 : : */
545 : : ErrorCode get_params( EntityHandle ent, int& i, int& j, int& k, int& dir ) const;
546 : :
547 : : //! Get parametric coordinates of the specified entity, intermediate entities not allowed (no
548 : : //! dir parameter)
549 : : /** This function returns MB_ENTITY_NOT_FOUND if the entity is not
550 : : * in this ScdBox, or MB_FAILURE if the entity is an intermediate-dimension entity.
551 : : * \param ent Entity being queried
552 : : * \param i Parametric coordinates returned
553 : : * \param j Parametric coordinates returned
554 : : * \param k Parametric coordinates returned
555 : : */
556 : : ErrorCode get_params( EntityHandle ent, int& i, int& j, int& k ) const;
557 : :
558 : : //! Get parametric coordinates of the specified entity
559 : : /** This function returns MB_ENTITY_NOT_FOUND if the entity is not
560 : : * in this ScdBox.
561 : : * \param ent Entity being queried
562 : : * \param ijkd Parametric coordinates returned (including direction, in case of
563 : : * getting adjacent edges (2d, 3d) or faces (3d))
564 : : */
565 : : ErrorCode get_params( EntityHandle ent, HomCoord& ijkd ) const;
566 : :
567 : : /** \brief Get the adjacent edge or face at a parametric location
568 : : * This function gets the left (i=0), front (j=0), or bottom (k=0) edge or face for a parametric
569 : : * element. Left, front, or bottom is indicated by dir = 0, 1, or 2, resp. All edges and faces
570 : : * in a structured mesh block can be accessed using these parameters. \param dim Dimension of
571 : : * adjacent entity being requested \param i Parametric coordinates of cell being evaluated
572 : : * \param j Parametric coordinates of cell being evaluated
573 : : * \param k Parametric coordinates of cell being evaluated
574 : : * \param dir Direction (0, 1, or 2), for getting adjacent edges (2d, 3d) or faces (3d)
575 : : * \param ent Entity returned from this function
576 : : * \param create_if_missing If true, creates the entity if it doesn't already exist
577 : : */
578 : : ErrorCode get_adj_edge_or_face( int dim, int i, int j, int k, int dir, EntityHandle& ent,
579 : : bool create_if_missing = true ) const;
580 : :
581 : : //! Return whether the box contains the parameters passed in
582 : : /**
583 : : * \param i Parametric coordinates being evaluated
584 : : * \param j Parametric coordinates being evaluated
585 : : * \param k Parametric coordinates being evaluated
586 : : */
587 : : bool contains( int i, int j, int k ) const;
588 : :
589 : : //! Return whether the box contains the parameters passed in
590 : : /**
591 : : * \param i Parametric coordinates being evaluated
592 : : * \param j Parametric coordinates being evaluated
593 : : * \param k Parametric coordinates being evaluated
594 : : */
595 : : bool contains( const HomCoord& ijk ) const;
596 : :
597 : : //! Set/Get the entity set representing the box
598 : : void box_set( EntityHandle this_set );
599 : : EntityHandle box_set();
600 : :
601 : : //! Get coordinate arrays for vertex coordinates for a structured block
602 : : /** Returns error if there isn't a single vertex sequence associated with this structured block
603 : : * \param xc X coordinate array pointer returned
604 : : * \param yc Y coordinate array pointer returned
605 : : * \param zc Z coordinate array pointer returned
606 : : */
607 : : ErrorCode get_coordinate_arrays( double*& xc, double*& yc, double*& zc );
608 : :
609 : : //! Get read-only coordinate arrays for vertex coordinates for a structured block
610 : : /** Returns error if there isn't a single vertex sequence associated with this structured block
611 : : * \param xc X coordinate array pointer returned
612 : : * \param yc Y coordinate array pointer returned
613 : : * \param zc Z coordinate array pointer returned
614 : : */
615 : : ErrorCode get_coordinate_arrays( const double*& xc, const double*& yc, const double*& zc ) const;
616 : :
617 : : //! Return whether box is locally periodic in i
618 : : /** Return whether box is locally periodic in i
619 : : * \return True if box is locally periodic in i direction
620 : : */
621 : : bool locally_periodic_i() const;
622 : :
623 : : //! Return whether box is locally periodic in j
624 : : /** Return whether box is locally periodic in j
625 : : * \return True if box is locally periodic in j direction
626 : : */
627 : : bool locally_periodic_j() const;
628 : :
629 : : //! Return whether box is locally periodic in k
630 : : /** Return whether box is locally periodic in k
631 : : * \return True if box is locally periodic in k direction
632 : : */
633 : : bool locally_periodic_k() const;
634 : :
635 : : //! Set local periodicity
636 : : /**
637 : : * \param lperiodic Vector of ijk periodicities to set this box to
638 : : */
639 : : void locally_periodic( bool lperiodic[3] );
640 : :
641 : : //! Get local periodicity
642 : : /**
643 : : * \return Vector of ijk periodicities for this box
644 : : */
645 : : const int* locally_periodic() const;
646 : :
647 : : //! Return parallel data
648 : : /** Return parallel data, if there is any
649 : : * \return par_data Parallel data set on this box
650 : : */
651 : 8470 : ScdParData& par_data()
652 : : {
653 : 8470 : return parData;
654 : : }
655 : :
656 : : //! Return parallel data
657 : : /** Return parallel data, if there is any
658 : : * \return par_data Parallel data set on this box
659 : : */
660 : : const ScdParData& par_data() const
661 : : {
662 : : return parData;
663 : : }
664 : :
665 : : //! set parallel data
666 : : /** Set parallel data for this box
667 : : * \param par_data Parallel data to be set on this box
668 : : */
669 : 0 : void par_data( const ScdParData& par_datap )
670 : : {
671 : 0 : parData = par_datap;
672 : 0 : }
673 : :
674 : : private:
675 : : //! Constructor
676 : : /** Create a structured box instance; this constructor is private because it should only be
677 : : * called from ScdInterface, a friend class. This constructor takes two sequences, one of which
678 : : * can be NULL. If both sequences come in non-NULL, the first should be a VertexSequence*
679 : : * corresponding to a structured vertex sequence and the second should be a
680 : : * StructuredElementSeq*. If the 2nd is NULL, the first can be either of those types. The
681 : : * other members of this class are taken from the sequences (e.g. parametric space) or the box
682 : : * set argument. Tags on the box set should be set from the caller. \param sc_impl A
683 : : * ScdInterface instance \param box_set Entity set representing this rectangle \param seq1 An
684 : : * EntitySequence (see ScdBox description) \param seq2 An EntitySequence (see ScdBox
685 : : * description), or NULL
686 : : */
687 : : ScdBox( ScdInterface* sc_impl, EntityHandle box_set, EntitySequence* seq1, EntitySequence* seq2 = NULL );
688 : :
689 : : //! function to get vertex handle directly from sequence
690 : : /** \param i Parameter being queried
691 : : * \param j Parameter being queried
692 : : * \param k Parameter being queried
693 : : */
694 : : EntityHandle get_vertex_from_seq( int i, int j, int k ) const;
695 : :
696 : : //! set the vertex sequence
697 : : ErrorCode vert_dat( ScdVertexData* vert_dat );
698 : :
699 : : //! get the vertex sequence
700 : : ScdVertexData* vert_dat() const;
701 : :
702 : : //! set the element sequence
703 : : ErrorCode elem_seq( EntitySequence* elem_seq );
704 : :
705 : : //! get the element sequence
706 : : StructuredElementSeq* elem_seq() const;
707 : :
708 : : //! Set the starting vertex handle for this box
709 : : void start_vertex( EntityHandle startv );
710 : :
711 : : //! Set the starting entity handle for this box
712 : : void start_element( EntityHandle starte );
713 : :
714 : : //! interface instance
715 : : ScdInterface* scImpl;
716 : :
717 : : //! entity set representing this box
718 : : EntityHandle boxSet;
719 : :
720 : : //! vertex sequence this box represents, if there's only one, otherwise they're
721 : : //! retrieved from the element sequence
722 : : ScdVertexData* vertDat;
723 : :
724 : : //! element sequence this box represents
725 : : StructuredElementSeq* elemSeq;
726 : :
727 : : //! starting vertex handle for this box
728 : : EntityHandle startVertex;
729 : :
730 : : //! starting element handle for this box
731 : : EntityHandle startElem;
732 : :
733 : : //! lower and upper corners
734 : : int boxDims[6];
735 : :
736 : : //! is locally periodic in i or j or k
737 : : int locallyPeriodic[3];
738 : :
739 : : //! parallel data associated with this box, if any
740 : : ScdParData parData;
741 : :
742 : : //! parameter extents
743 : : HomCoord boxSize;
744 : :
745 : : //! convenience parameters, (boxSize[1]-1)*(boxSize[0]-1) and boxSize[0]-1
746 : : int boxSizeIJ;
747 : : int boxSizeIJM1;
748 : : int boxSizeIM1;
749 : : };
750 : :
751 : 51 : inline ErrorCode ScdInterface::compute_partition( int np, int nr, const ScdParData& par_data, int* ldims,
752 : : int* lperiodic, int* pdims )
753 : : {
754 : 51 : ErrorCode rval = MB_SUCCESS;
755 [ + + + + : 51 : switch( par_data.partMethod )
+ - ]
756 : : {
757 : : case ScdParData::ALLJORKORI:
758 : : case -1:
759 : 10 : rval = compute_partition_alljorkori( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims );
760 : 10 : break;
761 : : case ScdParData::ALLJKBAL:
762 : 10 : rval = compute_partition_alljkbal( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims );
763 : 10 : break;
764 : : case ScdParData::SQIJ:
765 : 10 : rval = compute_partition_sqij( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims );
766 : 10 : break;
767 : : case ScdParData::SQJK:
768 : 10 : rval = compute_partition_sqjk( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims );
769 : 10 : break;
770 : : case ScdParData::SQIJK:
771 : 11 : rval = compute_partition_sqijk( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims );
772 : 11 : break;
773 : : default:
774 : 0 : rval = MB_FAILURE;
775 : 0 : break;
776 : : }
777 : :
778 : 51 : return rval;
779 : : }
780 : :
781 : 288 : inline ErrorCode ScdInterface::compute_partition_alljorkori( int np, int nr, const int gijk[6],
782 : : const int* const gperiodic, int* ldims, int* lperiodic,
783 : : int* pijk )
784 : : {
785 : : // partition *the elements* over the parametric space; 1d partition for now, in the j, k, or i
786 : : // parameters
787 : : int tmp_lp[3], tmp_pijk[3];
788 [ - + ]: 288 : if( !lperiodic ) lperiodic = tmp_lp;
789 [ - + ]: 288 : if( !pijk ) pijk = tmp_pijk;
790 : :
791 [ + + ]: 1152 : for( int i = 0; i < 3; i++ )
792 : 864 : lperiodic[i] = gperiodic[i];
793 : :
794 [ - + ]: 288 : if( np == 1 )
795 : : {
796 [ # # ]: 0 : if( ldims )
797 : : {
798 : 0 : ldims[0] = gijk[0];
799 : 0 : ldims[3] = gijk[3];
800 : 0 : ldims[1] = gijk[1];
801 : 0 : ldims[4] = gijk[4];
802 : 0 : ldims[2] = gijk[2];
803 : 0 : ldims[5] = gijk[5];
804 : : }
805 : 0 : pijk[0] = pijk[1] = pijk[2] = 1;
806 : : }
807 : : else
808 : : {
809 [ + - ]: 288 : if( gijk[4] - gijk[1] > np )
810 : : {
811 : : // partition j over procs
812 : 288 : int dj = ( gijk[4] - gijk[1] ) / np;
813 : 288 : int extra = ( gijk[4] - gijk[1] ) % np;
814 [ + - ]: 288 : ldims[1] = gijk[1] + nr * dj + std::min( nr, extra );
815 [ + + ]: 288 : ldims[4] = ldims[1] + dj + ( nr < extra ? 1 : 0 );
816 : :
817 [ - + ][ # # ]: 288 : if( gperiodic[1] && np > 1 )
818 : : {
819 : 0 : lperiodic[1] = 0;
820 : 0 : ldims[4]++;
821 : : }
822 : :
823 : 288 : ldims[2] = gijk[2];
824 : 288 : ldims[5] = gijk[5];
825 : 288 : ldims[0] = gijk[0];
826 : 288 : ldims[3] = gijk[3];
827 : 288 : pijk[0] = pijk[2] = 1;
828 : 288 : pijk[1] = np;
829 : : }
830 [ # # ]: 0 : else if( gijk[5] - gijk[2] > np )
831 : : {
832 : : // partition k over procs
833 : 0 : int dk = ( gijk[5] - gijk[2] ) / np;
834 : 0 : int extra = ( gijk[5] - gijk[2] ) % np;
835 [ # # ]: 0 : ldims[2] = gijk[2] + nr * dk + std::min( nr, extra );
836 [ # # ]: 0 : ldims[5] = ldims[2] + dk + ( nr < extra ? 1 : 0 );
837 : :
838 : 0 : ldims[1] = gijk[1];
839 : 0 : ldims[4] = gijk[4];
840 : 0 : ldims[0] = gijk[0];
841 : 0 : ldims[3] = gijk[3];
842 : 0 : pijk[0] = pijk[1] = 1;
843 : 0 : pijk[2] = np;
844 : : }
845 [ # # ]: 0 : else if( gijk[3] - gijk[0] > np )
846 : : {
847 : : // partition i over procs
848 : 0 : int di = ( gijk[3] - gijk[0] ) / np;
849 : 0 : int extra = ( gijk[3] - gijk[0] ) % np;
850 [ # # ]: 0 : ldims[0] = gijk[0] + nr * di + std::min( nr, extra );
851 [ # # ]: 0 : ldims[3] = ldims[0] + di + ( nr < extra ? 1 : 0 );
852 : :
853 [ # # ][ # # ]: 0 : if( gperiodic[0] && np > 1 )
854 : : {
855 : 0 : lperiodic[0] = 0;
856 : 0 : ldims[3]++;
857 : : }
858 : :
859 : 0 : ldims[2] = gijk[2];
860 : 0 : ldims[5] = gijk[5];
861 : 0 : ldims[1] = gijk[1];
862 : 0 : ldims[4] = gijk[4];
863 : :
864 : 0 : pijk[1] = pijk[2] = 1;
865 : 0 : pijk[0] = np;
866 : : }
867 : : else
868 : : {
869 : : // Couldn't find a suitable partition...
870 : 0 : return MB_FAILURE;
871 : : }
872 : : }
873 : :
874 : 288 : return MB_SUCCESS;
875 : : }
876 : :
877 : 129 : inline ErrorCode ScdInterface::compute_partition_alljkbal( int np, int nr, const int gijk[6],
878 : : const int* const gperiodic, int* ldims, int* lperiodic,
879 : : int* pijk )
880 : : {
881 : : int tmp_lp[3], tmp_pijk[3];
882 [ - + ]: 129 : if( !lperiodic ) lperiodic = tmp_lp;
883 [ - + ]: 129 : if( !pijk ) pijk = tmp_pijk;
884 : :
885 [ + + ]: 516 : for( int i = 0; i < 3; i++ )
886 : 387 : lperiodic[i] = gperiodic[i];
887 : :
888 [ - + ]: 129 : if( np == 1 )
889 : : {
890 [ # # ]: 0 : if( ldims )
891 : : {
892 : 0 : ldims[0] = gijk[0];
893 : 0 : ldims[3] = gijk[3];
894 : 0 : ldims[1] = gijk[1];
895 : 0 : ldims[4] = gijk[4];
896 : 0 : ldims[2] = gijk[2];
897 : 0 : ldims[5] = gijk[5];
898 : : }
899 : 0 : pijk[0] = pijk[1] = pijk[2] = 1;
900 : : }
901 : : else
902 : : {
903 : : // improved, possibly 2-d partition
904 [ + - ]: 129 : std::vector< double > kfactors;
905 [ + - ]: 129 : kfactors.push_back( 1 );
906 : 129 : int K = gijk[5] - gijk[2];
907 [ + + ]: 2193 : for( int i = 2; i < K; i++ )
908 [ + + ][ + + ]: 2064 : if( !( K % i ) && !( np % i ) ) kfactors.push_back( i );
[ + - ]
909 [ + - ]: 129 : kfactors.push_back( K );
910 : :
911 : : // compute the ideal nj and nk
912 : 129 : int J = gijk[4] - gijk[1];
913 : 129 : double njideal = sqrt( ( (double)( np * J ) ) / ( (double)K ) );
914 : 129 : double nkideal = ( njideal * K ) / J;
915 : :
916 : : int nk, nj;
917 [ - + ]: 129 : if( nkideal < 1.0 )
918 : : {
919 : 0 : nk = 1;
920 : 0 : nj = np;
921 : : }
922 : : else
923 : : {
924 [ + - ]: 129 : std::vector< double >::iterator vit = std::lower_bound( kfactors.begin(), kfactors.end(), nkideal );
925 [ + - ][ - + ]: 129 : if( vit == kfactors.begin() )
926 : 0 : nk = 1;
927 : : else
928 [ + - ][ + - ]: 129 : nk = (int)*( --vit );
929 : 129 : nj = np / nk;
930 : : }
931 : :
932 : 129 : int dk = K / nk;
933 : 129 : int dj = J / nj;
934 : :
935 : 129 : ldims[2] = gijk[2] + ( nr % nk ) * dk;
936 : 129 : ldims[5] = ldims[2] + dk;
937 : :
938 : 129 : int extra = J % nj;
939 : :
940 [ + - ]: 129 : ldims[1] = gijk[1] + ( nr / nk ) * dj + std::min( nr / nk, extra );
941 [ - + ]: 129 : ldims[4] = ldims[1] + dj + ( nr / nk < extra ? 1 : 0 );
942 : :
943 : 129 : ldims[0] = gijk[0];
944 : 129 : ldims[3] = gijk[3];
945 : :
946 [ - + ][ # # ]: 129 : if( gperiodic[1] && np > 1 )
947 : : {
948 : 0 : lperiodic[1] = 0;
949 [ # # ]: 0 : if( nr / nk == nj - 1 ) { ldims[1]++; }
950 : : }
951 : :
952 : 129 : pijk[0] = 1;
953 : 129 : pijk[1] = nj;
954 : 129 : pijk[2] = nk;
955 : : }
956 : :
957 : 129 : return MB_SUCCESS;
958 : : }
959 : :
960 : 138 : inline ErrorCode ScdInterface::compute_partition_sqij( int np, int nr, const int gijk[6], const int* const gperiodic,
961 : : int* ldims, int* lperiodic, int* pijk )
962 : : {
963 : : int tmp_lp[3], tmp_pijk[3];
964 [ - + ]: 138 : if( !lperiodic ) lperiodic = tmp_lp;
965 [ - + ]: 138 : if( !pijk ) pijk = tmp_pijk;
966 : :
967 : : // square IxJ partition
968 : :
969 [ + + ]: 552 : for( int i = 0; i < 3; i++ )
970 : 414 : lperiodic[i] = gperiodic[i];
971 : :
972 [ - + ]: 138 : if( np == 1 )
973 : : {
974 [ # # ]: 0 : if( ldims )
975 : : {
976 : 0 : ldims[0] = gijk[0];
977 : 0 : ldims[3] = gijk[3];
978 : 0 : ldims[1] = gijk[1];
979 : 0 : ldims[4] = gijk[4];
980 : 0 : ldims[2] = gijk[2];
981 : 0 : ldims[5] = gijk[5];
982 : : }
983 : 0 : pijk[0] = pijk[1] = pijk[2] = 1;
984 : : }
985 : : else
986 : : {
987 [ + - ][ + - ]: 276 : std::vector< double > pfactors, ppfactors;
988 [ + + ]: 960 : for( int i = 2; i <= np / 2; i++ )
989 [ + + ]: 822 : if( !( np % i ) )
990 : : {
991 [ + - ]: 366 : pfactors.push_back( i );
992 [ + - ]: 366 : ppfactors.push_back( ( (double)( i * i ) ) / np );
993 : : }
994 [ + - ]: 138 : pfactors.push_back( np );
995 [ + - ]: 138 : ppfactors.push_back( (double)np );
996 : :
997 : : // ideally, Px/Py = I/J
998 : 138 : double ijratio = ( (double)( gijk[3] - gijk[0] ) ) / ( (double)( gijk[4] - gijk[1] ) );
999 : :
1000 : 138 : unsigned int ind = 0;
1001 [ + - ]: 138 : std::vector< double >::iterator optimal = std::lower_bound( ppfactors.begin(), ppfactors.end(), ijratio );
1002 [ + - ][ - + ]: 138 : if( optimal == ppfactors.end() ) { ind = ppfactors.size() - 1; }
1003 : : else
1004 : : {
1005 [ + - ]: 138 : ind = optimal - ppfactors.begin();
1006 [ + - ][ + - ]: 138 : if( ind && fabs( ppfactors[ind - 1] - ijratio ) < fabs( ppfactors[ind] - ijratio ) ) ind--;
[ + - ][ + - ]
[ + - ]
1007 : : }
1008 : :
1009 : : // VARIABLES DESCRIBING THE MESH:
1010 : : // pi, pj = # procs in i and j directions
1011 : : // nri, nrj = my proc's position in i, j directions
1012 : : // I, J = # edges/elements in i, j directions
1013 : : // iextra, jextra = # procs having extra edge in i/j direction
1014 : : // top_i, top_j = if true, I'm the last proc in the i/j direction
1015 : : // i, j = # edges locally in i/j direction, *not* including one for iextra/jextra
1016 [ + - ]: 138 : int pi = pfactors[ind];
1017 : 138 : int pj = np / pi;
1018 : :
1019 : 138 : int I = ( gijk[3] - gijk[0] ), J = ( gijk[4] - gijk[1] );
1020 : 138 : int iextra = I % pi, jextra = J % pj, i = I / pi, j = J / pj;
1021 : 138 : int nri = nr % pi, nrj = nr / pi;
1022 : :
1023 [ + - ]: 138 : if( ldims )
1024 : : {
1025 [ + - ]: 138 : ldims[0] = gijk[0] + i * nri + std::min( iextra, nri );
1026 [ - + ]: 138 : ldims[3] = ldims[0] + i + ( nri < iextra ? 1 : 0 );
1027 [ + - ]: 138 : ldims[1] = gijk[1] + j * nrj + std::min( jextra, nrj );
1028 [ - + ]: 138 : ldims[4] = ldims[1] + j + ( nrj < jextra ? 1 : 0 );
1029 : :
1030 : 138 : ldims[2] = gijk[2];
1031 : 138 : ldims[5] = gijk[5];
1032 : :
1033 [ - + ][ # # ]: 138 : if( gperiodic[0] && pi > 1 )
1034 : : {
1035 : 0 : lperiodic[0] = 0;
1036 [ # # ]: 0 : if( nri == pi - 1 ) ldims[3]++;
1037 : : }
1038 [ - + ][ # # ]: 138 : if( gperiodic[1] && pj > 1 )
1039 : : {
1040 : 0 : lperiodic[1] = 0;
1041 [ # # ]: 0 : if( nrj == pj - 1 ) ldims[4]++;
1042 : : }
1043 : : }
1044 : :
1045 : 138 : pijk[0] = pi;
1046 : 138 : pijk[1] = pj;
1047 : 138 : pijk[2] = 1;
1048 : : }
1049 : :
1050 : 138 : return MB_SUCCESS;
1051 : : }
1052 : :
1053 : 108 : inline ErrorCode ScdInterface::compute_partition_sqjk( int np, int nr, const int gijk[6], const int* const gperiodic,
1054 : : int* ldims, int* lperiodic, int* pijk )
1055 : : {
1056 : : int tmp_lp[3], tmp_pijk[3];
1057 [ - + ]: 108 : if( !lperiodic ) lperiodic = tmp_lp;
1058 [ - + ]: 108 : if( !pijk ) pijk = tmp_pijk;
1059 : :
1060 : : // square JxK partition
1061 [ + + ]: 432 : for( int i = 0; i < 3; i++ )
1062 : 324 : lperiodic[i] = gperiodic[i];
1063 : :
1064 [ - + ]: 108 : if( np == 1 )
1065 : : {
1066 [ # # ]: 0 : if( ldims )
1067 : : {
1068 : 0 : ldims[0] = gijk[0];
1069 : 0 : ldims[3] = gijk[3];
1070 : 0 : ldims[1] = gijk[1];
1071 : 0 : ldims[4] = gijk[4];
1072 : 0 : ldims[2] = gijk[2];
1073 : 0 : ldims[5] = gijk[5];
1074 : : }
1075 : 0 : pijk[0] = pijk[1] = pijk[2] = 1;
1076 : : }
1077 : : else
1078 : : {
1079 [ + - ][ + - ]: 216 : std::vector< double > pfactors, ppfactors;
1080 [ + + ]: 1476 : for( int p = 2; p <= np; p++ )
1081 [ + + ]: 1368 : if( !( np % p ) )
1082 : : {
1083 [ + - ]: 390 : pfactors.push_back( p );
1084 [ + - ]: 390 : ppfactors.push_back( ( (double)( p * p ) ) / np );
1085 : : }
1086 : :
1087 : : // ideally, Pj/Pk = J/K
1088 : : int pj, pk;
1089 [ - + ]: 108 : if( gijk[5] == gijk[2] )
1090 : : {
1091 : 0 : pk = 1;
1092 : 0 : pj = np;
1093 : : }
1094 : : else
1095 : : {
1096 : 108 : double jkratio = ( (double)( gijk[4] - gijk[1] ) ) / ( (double)( gijk[5] - gijk[2] ) );
1097 : :
1098 [ + - ]: 108 : std::vector< double >::iterator vit = std::lower_bound( ppfactors.begin(), ppfactors.end(), jkratio );
1099 [ + - ][ - + ]: 108 : if( vit == ppfactors.end() )
1100 [ # # ]: 0 : --vit;
1101 [ + - ][ + - ]: 108 : else if( vit != ppfactors.begin() && fabs( *( vit - 1 ) - jkratio ) < fabs( ( *vit ) - jkratio ) )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + -
# # # # #
# ]
1102 [ + - ]: 108 : --vit;
1103 [ + - ]: 108 : int ind = vit - ppfactors.begin();
1104 : :
1105 : 108 : pj = 1;
1106 [ + - ][ + - ]: 108 : if( ind >= 0 && !pfactors.empty() ) pfactors[ind];
[ + - ][ + - ]
1107 : 108 : pk = np / pj;
1108 : : }
1109 : :
1110 : 108 : int K = ( gijk[5] - gijk[2] ), J = ( gijk[4] - gijk[1] );
1111 : 108 : int jextra = J % pj, kextra = K % pk, j = J / pj, k = K / pk;
1112 : 108 : int nrj = nr % pj, nrk = nr / pj;
1113 [ + - ]: 108 : ldims[1] = gijk[1] + j * nrj + std::min( jextra, nrj );
1114 [ - + ]: 108 : ldims[4] = ldims[1] + j + ( nrj < jextra ? 1 : 0 );
1115 [ + - ]: 108 : ldims[2] = gijk[2] + k * nrk + std::min( kextra, nrk );
1116 [ + + ]: 108 : ldims[5] = ldims[2] + k + ( nrk < kextra ? 1 : 0 );
1117 : :
1118 : 108 : ldims[0] = gijk[0];
1119 : 108 : ldims[3] = gijk[3];
1120 : :
1121 [ - + ][ # # ]: 108 : if( gperiodic[1] && pj > 1 )
1122 : : {
1123 : 0 : lperiodic[1] = 0;
1124 [ # # ]: 0 : if( nrj == pj - 1 ) ldims[4]++;
1125 : : }
1126 : :
1127 : 108 : pijk[0] = 1;
1128 : 108 : pijk[1] = pj;
1129 : 108 : pijk[2] = pk;
1130 : : }
1131 : :
1132 : 108 : return MB_SUCCESS;
1133 : : }
1134 : :
1135 : 319 : inline ErrorCode ScdInterface::compute_partition_sqijk( int np, int nr, const int* const gijk,
1136 : : const int* const gperiodic, int* ldims, int* lperiodic,
1137 : : int* pijk )
1138 : : {
1139 [ + - ][ + - ]: 319 : if( gperiodic[0] || gperiodic[1] || gperiodic[2] ) return MB_FAILURE;
[ - + ]
1140 : :
1141 : : int tmp_lp[3], tmp_pijk[3];
1142 [ - + ]: 319 : if( !lperiodic ) lperiodic = tmp_lp;
1143 [ - + ]: 319 : if( !pijk ) pijk = tmp_pijk;
1144 : :
1145 : : // square IxJxK partition
1146 : :
1147 [ + + ]: 1276 : for( int i = 0; i < 3; i++ )
1148 : 957 : lperiodic[i] = gperiodic[i];
1149 : :
1150 [ - + ]: 319 : if( np == 1 )
1151 : : {
1152 [ # # ]: 0 : if( ldims )
1153 [ # # ]: 0 : for( int i = 0; i < 6; i++ )
1154 : 0 : ldims[i] = gijk[i];
1155 : 0 : pijk[0] = pijk[1] = pijk[2] = 1;
1156 : 0 : return MB_SUCCESS;
1157 : : }
1158 : :
1159 [ + - ]: 319 : std::vector< int > pfactors;
1160 [ + - ]: 319 : pfactors.push_back( 1 );
1161 [ + + ]: 2186 : for( int i = 2; i <= np / 2; i++ )
1162 [ + + ][ + - ]: 1867 : if( !( np % i ) ) pfactors.push_back( i );
1163 [ + - ]: 319 : pfactors.push_back( np );
1164 : :
1165 : : // test for IJ, JK, IK
1166 : : int IJK[3], dIJK[3];
1167 [ + + ]: 1276 : for( int i = 0; i < 3; i++ )
1168 [ + - ]: 957 : IJK[i] = std::max( gijk[3 + i] - gijk[i], 1 );
1169 : : // order IJK from lo to hi
1170 : 319 : int lo = 0, hi = 0;
1171 [ + + ]: 957 : for( int i = 1; i < 3; i++ )
1172 : : {
1173 [ + + ]: 638 : if( IJK[i] < IJK[lo] ) lo = i;
1174 [ - + ]: 638 : if( IJK[i] > IJK[hi] ) hi = i;
1175 : : }
1176 [ + + ]: 319 : if( lo == hi ) hi = ( lo + 1 ) % 3;
1177 : 319 : int mid = 3 - lo - hi;
1178 : : // search for perfect subdivision of np that balances #cells
1179 : 319 : int perfa_best = -1, perfb_best = -1;
1180 : 319 : double ratio = 0.0;
1181 [ + + ]: 1792 : for( int po = 0; po < (int)pfactors.size(); po++ )
1182 : : {
1183 [ + - ][ + - ]: 2627 : for( int pi = po; pi < (int)pfactors.size() && np / ( pfactors[po] * pfactors[pi] ) >= pfactors[pi]; pi++ )
[ + - ][ + - ]
[ + + ][ + + ]
1184 : : {
1185 : : int p3 =
1186 [ + - ][ + - ]: 1154 : std::find( pfactors.begin(), pfactors.end(), np / ( pfactors[po] * pfactors[pi] ) ) - pfactors.begin();
[ + - ][ + - ]
1187 [ + - ][ + - ]: 1154 : if( p3 == (int)pfactors.size() || pfactors[po] * pfactors[pi] * pfactors[p3] != np )
[ + - ][ + - ]
[ - + ][ - + ]
1188 : 0 : continue; // po*pi should exactly factor np
1189 [ + - ][ - + ]: 1154 : assert( po <= pi && pi <= p3 );
1190 : : // by definition, po <= pi <= p3
1191 : : double minl =
1192 [ + - ][ + - ]: 1154 : std::min( std::min( IJK[lo] / pfactors[po], IJK[mid] / pfactors[pi] ), IJK[hi] / pfactors[p3] ),
[ + - ][ + - ]
[ + - ]
1193 : : maxl =
1194 [ + - ][ + - ]: 1154 : std::max( std::max( IJK[lo] / pfactors[po], IJK[mid] / pfactors[pi] ), IJK[hi] / pfactors[p3] );
[ + - ][ + - ]
[ + - ]
1195 [ + + ]: 1154 : if( minl / maxl > ratio )
1196 : : {
1197 : 896 : ratio = minl / maxl;
1198 : 896 : perfa_best = po;
1199 : 896 : perfb_best = pi;
1200 : : }
1201 : : }
1202 : : }
1203 [ + - ][ - + ]: 319 : if( perfa_best == -1 || perfb_best == -1 ) return MB_FAILURE;
1204 : :
1205 : : // VARIABLES DESCRIBING THE MESH:
1206 : : // pijk[i] = # procs in direction i
1207 : : // numr[i] = my proc's position in direction i
1208 : : // dIJK[i] = # edges/elements in direction i
1209 : : // extra[i]= # procs having extra edge in direction i
1210 : : // top[i] = if true, I'm the last proc in direction i
1211 : :
1212 [ + - ]: 319 : pijk[lo] = pfactors[perfa_best];
1213 [ + - ]: 319 : pijk[mid] = pfactors[perfb_best];
1214 [ + - ][ + - ]: 319 : pijk[hi] = ( np / ( pfactors[perfa_best] * pfactors[perfb_best] ) );
1215 : 319 : int extra[3] = { 0, 0, 0 }, numr[3];
1216 [ + + ]: 1276 : for( int i = 0; i < 3; i++ )
1217 : : {
1218 : 957 : dIJK[i] = IJK[i] / pijk[i];
1219 : 957 : extra[i] = IJK[i] % pijk[i];
1220 : : }
1221 : 319 : numr[2] = nr / ( pijk[0] * pijk[1] );
1222 : 319 : int rem = nr % ( pijk[0] * pijk[1] );
1223 : 319 : numr[1] = rem / pijk[0];
1224 : 319 : numr[0] = rem % pijk[0];
1225 [ + + ]: 1276 : for( int i = 0; i < 3; i++ )
1226 : : {
1227 : 957 : extra[i] = IJK[i] % dIJK[i];
1228 [ + - ]: 957 : ldims[i] = gijk[i] + numr[i] * dIJK[i] + std::min( extra[i], numr[i] );
1229 [ - + ]: 957 : ldims[3 + i] = ldims[i] + dIJK[i] + ( numr[i] < extra[i] ? 1 : 0 );
1230 : : }
1231 : :
1232 : 319 : return MB_SUCCESS;
1233 : : }
1234 : :
1235 : 0 : inline int ScdInterface::gtol( const int* gijk, int i, int j, int k )
1236 : : {
1237 : 0 : return ( ( k - gijk[2] ) * ( gijk[3] - gijk[0] + 1 ) * ( gijk[4] - gijk[1] + 1 ) +
1238 : 0 : ( j - gijk[1] ) * ( gijk[3] - gijk[0] + 1 ) + i - gijk[0] );
1239 : : }
1240 : :
1241 : 0 : inline ErrorCode ScdInterface::get_indices( const int* const ldims, const int* const rdims, const int* const across_bdy,
1242 : : int* face_dims, std::vector< int >& shared_indices )
1243 : : {
1244 : : // check for going across periodic bdy and face_dims not in my ldims (I'll always be on top in
1245 : : // that case)...
1246 [ # # ][ # # ]: 0 : if( across_bdy[0] > 0 && face_dims[0] != ldims[3] )
1247 : 0 : face_dims[0] = face_dims[3] = ldims[3];
1248 [ # # ][ # # ]: 0 : else if( across_bdy[0] < 0 && face_dims[0] != ldims[0] )
1249 : 0 : face_dims[0] = face_dims[3] = ldims[0];
1250 [ # # ][ # # ]: 0 : if( across_bdy[1] > 0 && face_dims[1] != ldims[4] )
1251 : 0 : face_dims[1] = face_dims[4] = ldims[4];
1252 [ # # ][ # # ]: 0 : else if( across_bdy[1] < 0 && face_dims[1] != ldims[1] )
1253 : 0 : face_dims[0] = face_dims[3] = ldims[1];
1254 : :
1255 [ # # ]: 0 : for( int k = face_dims[2]; k <= face_dims[5]; k++ )
1256 [ # # ]: 0 : for( int j = face_dims[1]; j <= face_dims[4]; j++ )
1257 [ # # ]: 0 : for( int i = face_dims[0]; i <= face_dims[3]; i++ )
1258 [ # # ]: 0 : shared_indices.push_back( gtol( ldims, i, j, k ) );
1259 : :
1260 [ # # ][ # # ]: 0 : if( across_bdy[0] > 0 && face_dims[0] != rdims[0] )
1261 : 0 : face_dims[0] = face_dims[3] = rdims[0];
1262 [ # # ][ # # ]: 0 : else if( across_bdy[0] < 0 && face_dims[0] != rdims[3] )
1263 : 0 : face_dims[0] = face_dims[3] = rdims[3];
1264 [ # # ][ # # ]: 0 : if( across_bdy[1] > 0 && face_dims[1] != rdims[1] )
1265 : 0 : face_dims[1] = face_dims[4] = rdims[1];
1266 [ # # ][ # # ]: 0 : else if( across_bdy[1] < 0 && face_dims[1] != rdims[4] )
1267 : 0 : face_dims[0] = face_dims[3] = rdims[4];
1268 : :
1269 [ # # ]: 0 : for( int k = face_dims[2]; k <= face_dims[5]; k++ )
1270 [ # # ]: 0 : for( int j = face_dims[1]; j <= face_dims[4]; j++ )
1271 [ # # ]: 0 : for( int i = face_dims[0]; i <= face_dims[3]; i++ )
1272 [ # # ]: 0 : shared_indices.push_back( gtol( rdims, i, j, k ) );
1273 : :
1274 : 0 : return MB_SUCCESS;
1275 : : }
1276 : :
1277 : 1521 : inline ErrorCode ScdInterface::get_neighbor( int np, int pfrom, const ScdParData& spd, const int* const dijk, int& pto,
1278 : : int* rdims, int* facedims, int* across_bdy )
1279 : : {
1280 [ + + ][ + + ]: 1521 : if( !dijk[0] && !dijk[1] && !dijk[2] )
[ + + ]
1281 : : {
1282 : : // not going anywhere, return
1283 : 50 : pto = -1;
1284 : 50 : return MB_SUCCESS;
1285 : : }
1286 : :
1287 [ + + + + : 1471 : switch( spd.partMethod )
+ - ]
1288 : : {
1289 : : case ScdParData::ALLJORKORI:
1290 : : case -1:
1291 : : return get_neighbor_alljorkori( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims,
1292 : 278 : across_bdy );
1293 : : case ScdParData::ALLJKBAL:
1294 : 299 : return get_neighbor_alljkbal( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy );
1295 : : case ScdParData::SQIJ:
1296 : 308 : return get_neighbor_sqij( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy );
1297 : : case ScdParData::SQJK:
1298 : 278 : return get_neighbor_sqjk( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy );
1299 : : case ScdParData::SQIJK:
1300 : 308 : return get_neighbor_sqijk( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy );
1301 : : default:
1302 : 0 : break;
1303 : : }
1304 : :
1305 : 0 : return MB_FAILURE;
1306 : : }
1307 : :
1308 : 0 : inline ErrorCode ScdInterface::tag_shared_vertices( ParallelComm* pcomm, EntityHandle seth )
1309 : : {
1310 : 0 : ScdBox* box = get_scd_box( seth );
1311 [ # # ]: 0 : if( !box )
1312 : : {
1313 : : // look for contained boxes
1314 [ # # ]: 0 : Range tmp_range;
1315 [ # # ]: 0 : ErrorCode rval = mbImpl->get_entities_by_type( seth, MBENTITYSET, tmp_range );
1316 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
1317 [ # # ][ # # ]: 0 : for( Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); ++rit )
[ # # ][ # # ]
[ # # ][ # # ]
1318 : : {
1319 [ # # ][ # # ]: 0 : box = get_scd_box( *rit );
1320 [ # # ]: 0 : if( box ) break;
1321 : 0 : }
1322 : : }
1323 : :
1324 [ # # ]: 0 : if( !box ) return MB_FAILURE;
1325 : :
1326 : 0 : return tag_shared_vertices( pcomm, box );
1327 : : }
1328 : :
1329 : 114 : inline ScdInterface* ScdBox::sc_impl() const
1330 : : {
1331 : 114 : return scImpl;
1332 : : }
1333 : :
1334 : 22 : inline EntityHandle ScdBox::start_vertex() const
1335 : : {
1336 : 22 : return startVertex;
1337 : : }
1338 : :
1339 : : inline void ScdBox::start_vertex( EntityHandle startv )
1340 : : {
1341 : : startVertex = startv;
1342 : : }
1343 : :
1344 : 71 : inline EntityHandle ScdBox::start_element() const
1345 : : {
1346 : 71 : return startElem;
1347 : : }
1348 : :
1349 : 13 : inline void ScdBox::start_element( EntityHandle starte )
1350 : : {
1351 : 13 : startElem = starte;
1352 : 13 : }
1353 : :
1354 : 39 : inline int ScdBox::num_elements() const
1355 : : {
1356 [ - + ]: 39 : if( !startElem ) return 0; // not initialized yet
1357 : :
1358 : : /* for a structured mesh, total number of elements is obtained by multiplying
1359 : : number of elements in each direction
1360 : : number of elements in each direction is given by number of vertices in that direction minus 1
1361 : : if periodic in that direction, the last vertex is the same as first one, count one more
1362 : : element
1363 : : */
1364 [ + - ][ + - ]: 39 : int num_e_i = ( -1 == boxSize[0] || 1 == boxSize[0] ) ? 1 : boxSize[0] - 1;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # # #
# # ]
1365 [ + + ]: 39 : if( locallyPeriodic[0] ) ++num_e_i;
1366 : :
1367 [ + - ][ + - ]: 39 : int num_e_j = ( -1 == boxSize[1] || 1 == boxSize[1] ) ? 1 : boxSize[1] - 1;
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # # #
# # ]
1368 [ + + ]: 39 : if( locallyPeriodic[1] ) ++num_e_j;
1369 : :
1370 [ + - ][ + - ]: 39 : int num_e_k = ( -1 == boxSize[2] || 1 == boxSize[2] ) ? 1 : boxSize[2] - 1;
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ + - ]
[ # # # #
# # ]
1371 [ - + ]: 39 : if( locallyPeriodic[2] ) ++num_e_k;
1372 : :
1373 : 39 : return num_e_i * num_e_j * num_e_k;
1374 : : }
1375 : :
1376 : 41 : inline int ScdBox::num_vertices() const
1377 : : {
1378 [ + - ][ + - ]: 41 : return boxSize[0] * ( !boxSize[1] ? 1 : boxSize[1] ) * ( !boxSize[2] ? 1 : boxSize[2] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
[ # # # # ]
1379 : : }
1380 : :
1381 : 8850 : inline const int* ScdBox::box_dims() const
1382 : : {
1383 : 8850 : return boxDims;
1384 : : }
1385 : :
1386 : 179 : inline HomCoord ScdBox::box_min() const
1387 : : {
1388 : 179 : return HomCoord( boxDims, 3 );
1389 : : }
1390 : :
1391 : 158 : inline HomCoord ScdBox::box_max() const
1392 : : {
1393 : 158 : return HomCoord( boxDims + 3, 3 );
1394 : : }
1395 : :
1396 : 29433 : inline HomCoord ScdBox::box_size() const
1397 : : {
1398 : 29433 : return boxSize;
1399 : : }
1400 : :
1401 : : inline void ScdBox::box_size( int* ijk ) const
1402 : : {
1403 : : ijk[0] = boxSize[0];
1404 : : ijk[1] = boxSize[1];
1405 : : ijk[2] = boxSize[2];
1406 : : }
1407 : :
1408 : : inline void ScdBox::box_size( int& i, int& j, int& k ) const
1409 : : {
1410 : : i = boxSize[0];
1411 : : j = boxSize[1];
1412 : : k = boxSize[2];
1413 : : }
1414 : :
1415 : 7012 : inline EntityHandle ScdBox::get_element( int i, int j, int k ) const
1416 : : {
1417 : 7012 : return ( !startElem
1418 : : ? 0
1419 [ + - ]: 7012 : : startElem + ( k - boxDims[2] ) * boxSizeIJM1 + ( j - boxDims[1] ) * boxSizeIM1 + i - boxDims[0] );
1420 : : }
1421 : :
1422 : 3506 : inline EntityHandle ScdBox::get_element( const HomCoord& ijk ) const
1423 : : {
1424 [ + - ][ + - ]: 3506 : return get_element( ijk[0], ijk[1], ijk[2] );
[ + - ][ + - ]
1425 : : }
1426 : :
1427 : 39681 : inline EntityHandle ScdBox::get_vertex( int i, int j, int k ) const
1428 : : {
1429 : : return ( vertDat
1430 [ - + ][ # # ]: 33161 : ? startVertex + ( boxDims[2] == -1 && boxDims[5] == -1 ? 0 : ( k - boxDims[2] ) ) * boxSizeIJ +
1431 [ - + ][ # # ]: 112523 : ( boxDims[1] == -1 && boxDims[4] == -1 ? 0 : ( j - boxDims[1] ) ) * boxSize[0] + i - boxDims[0]
[ + - ][ + + ]
[ # # ]
1432 [ + + ][ + - ]: 152204 : : get_vertex_from_seq( i, j, k ) );
1433 : : }
1434 : :
1435 : 13229 : inline EntityHandle ScdBox::get_vertex( const HomCoord& ijk ) const
1436 : : {
1437 [ + - ][ + - ]: 13229 : return get_vertex( ijk[0], ijk[1], ijk[2] );
[ + - ][ + - ]
1438 : : }
1439 : :
1440 : 26458 : inline bool ScdBox::contains( const HomCoord& ijk ) const
1441 : : {
1442 [ + - ][ + - ]: 26458 : return ( ijk >= HomCoord( boxDims, 3 ) && ijk <= HomCoord( boxDims + 3, 3 ) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # # # ]
1443 : : }
1444 : :
1445 : 13229 : inline bool ScdBox::contains( int i, int j, int k ) const
1446 : : {
1447 [ + - ]: 13229 : return contains( HomCoord( i, j, k ) );
1448 : : }
1449 : :
1450 : : inline void ScdBox::box_set( EntityHandle this_set )
1451 : : {
1452 : : boxSet = this_set;
1453 : : }
1454 : :
1455 : 19 : inline EntityHandle ScdBox::box_set()
1456 : : {
1457 : 19 : return boxSet;
1458 : : }
1459 : :
1460 : : inline ScdVertexData* ScdBox::vert_dat() const
1461 : : {
1462 : : return vertDat;
1463 : : }
1464 : :
1465 : : inline StructuredElementSeq* ScdBox::elem_seq() const
1466 : : {
1467 : : return elemSeq;
1468 : : }
1469 : :
1470 : : inline ErrorCode ScdBox::get_params( EntityHandle ent, int& i, int& j, int& k, int& dir ) const
1471 : : {
1472 : : HomCoord hc;
1473 : : ErrorCode rval = get_params( ent, hc );
1474 : : if( MB_SUCCESS == rval )
1475 : : {
1476 : : i = hc[0];
1477 : : j = hc[1];
1478 : : k = hc[2];
1479 : : dir = hc[3];
1480 : : }
1481 : :
1482 : : return rval;
1483 : : }
1484 : :
1485 : 13229 : inline ErrorCode ScdBox::get_params( EntityHandle ent, int& i, int& j, int& k ) const
1486 : : {
1487 [ + - ]: 13229 : HomCoord hc;
1488 [ + - ]: 13229 : ErrorCode rval = get_params( ent, hc );
1489 [ + - ]: 13229 : if( MB_SUCCESS == rval )
1490 : : {
1491 [ + - ]: 13229 : i = hc[0];
1492 [ + - ]: 13229 : j = hc[1];
1493 [ + - ]: 13229 : k = hc[2];
1494 : : }
1495 : :
1496 : 13229 : return rval;
1497 : : }
1498 : :
1499 : 21 : inline bool ScdBox::locally_periodic_i() const
1500 : : {
1501 : 21 : return locallyPeriodic[0];
1502 : : }
1503 : :
1504 : 21 : inline bool ScdBox::locally_periodic_j() const
1505 : : {
1506 : 21 : return locallyPeriodic[1];
1507 : : }
1508 : :
1509 : : inline bool ScdBox::locally_periodic_k() const
1510 : : {
1511 : : return locallyPeriodic[2];
1512 : : }
1513 : :
1514 : : inline void ScdBox::locally_periodic( bool lperiodic[3] )
1515 : : {
1516 : : for( int i = 0; i < 3; i++ )
1517 : : locallyPeriodic[i] = lperiodic[i];
1518 : : }
1519 : :
1520 : 8450 : inline const int* ScdBox::locally_periodic() const
1521 : : {
1522 : 8450 : return locallyPeriodic;
1523 : : }
1524 : :
1525 : : std::ostream& operator<<( std::ostream& str, const ScdParData& pd );
1526 : :
1527 : : } // namespace moab
1528 : : #endif
|