MOAB: Mesh Oriented datABase
(version 5.4.1)
|
A structured mesh interface for MOAB-based data. More...
#include <moab/ScdInterface.hpp>
Public Member Functions | |
ScdInterface (Interface *impl, bool find_boxes=false) | |
Constructor. | |
~ScdInterface () | |
Interface * | impl () const |
Return the MOAB Interface instance *. | |
ErrorCode | construct_box (HomCoord low, HomCoord high, const double *const coords, unsigned int num_coords, ScdBox *&new_box, int *const lperiodic=NULL, ScdParData *const par_data=NULL, bool assign_global_ids=false, int resolve_shared_ents=-1) |
Construct new structured mesh box, including both vertices and elements. | |
ErrorCode | create_scd_sequence (const HomCoord &low, const HomCoord &high, EntityType type, int starting_id, ScdBox *&new_box, int *is_periodic=NULL) |
Create a structured sequence of vertices, quads, or hexes. | |
ErrorCode | find_boxes (std::vector< ScdBox * > &boxes) |
Return all the structured mesh blocks in this MOAB instance, as ScdBox objects. | |
ErrorCode | find_boxes (Range &boxes) |
Return all the structured mesh blocks in this MOAB instance, as entity set handles. | |
ErrorCode | get_boxes (std::vector< ScdBox * > &boxes) |
Return all the structured mesh blocks known by ScdInterface (does not search) | |
Tag | box_dims_tag (bool create_if_missing=true) |
Return the tag marking the lower and upper corners of boxes. | |
Tag | global_box_dims_tag (bool create_if_missing=true) |
Return the tag marking the global lower and upper corners of boxes. | |
Tag | part_method_tag (bool create_if_missing=true) |
Return the tag marking the partitioning method used to partition the box in parallel. | |
Tag | box_periodic_tag (bool create_if_missing=true) |
Return the tag marking whether box is periodic in i and j. | |
Tag | box_set_tag (bool create_if_missing=true) |
Return the tag marking the ScdBox for a set. | |
ScdBox * | get_scd_box (EntityHandle eh) |
Return the ScdBox corresponding to the entity set passed in. | |
ErrorCode | tag_shared_vertices (ParallelComm *pcomm, EntityHandle seth) |
Tag vertices with sharing data for parallel representations. | |
ErrorCode | tag_shared_vertices (ParallelComm *pcomm, ScdBox *box) |
Tag vertices with sharing data for parallel representations. | |
Static Public Member Functions | |
static ErrorCode | compute_partition (int np, int nr, const ScdParData &par_data, int *ldims, int *lperiodic=NULL, int *pdims=NULL) |
Compute a partition of structured parameter space. | |
static ErrorCode | get_neighbor (int np, int nr, const ScdParData &spd, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
Protected Member Functions | |
ErrorCode | remove_box (ScdBox *box) |
Remove the box from the list on ScdInterface. | |
ErrorCode | add_box (ScdBox *box) |
Add the box to the list on ScdInterface. | |
Private Member Functions | |
ErrorCode | create_box_set (const HomCoord &low, const HomCoord &high, EntityHandle &scd_set, int *is_periodic=NULL) |
Create an entity set for a box, and tag with the parameters. | |
ErrorCode | assign_global_ids (ScdBox *box) |
assign global ids to vertices in this box | |
Static Private Member Functions | |
static ErrorCode | compute_partition_alljorkori (int np, int nr, const int gijk[6], const int *const gperiodic, int *lijk, int *lperiodic, int *pijk) |
Compute a partition of structured parameter space. | |
static ErrorCode | compute_partition_alljkbal (int np, int nr, const int gijk[6], const int *const gperiodic, int *lijk, int *lperiodic, int *pijk) |
Compute a partition of structured parameter space. | |
static ErrorCode | compute_partition_sqij (int np, int nr, const int gijk[6], const int *const gperiodic, int *lijk, int *lperiodic, int *pijk) |
Compute a partition of structured parameter space. | |
static ErrorCode | compute_partition_sqjk (int np, int nr, const int gijk[6], const int *const gperiodic, int *lijk, int *lperiodic, int *pijk) |
Compute a partition of structured parameter space. | |
static ErrorCode | compute_partition_sqijk (int np, int nr, const int gijk[6], const int *const gperiodic, int *lijk, int *lperiodic, int *pijk) |
Compute a partition of structured parameter space. | |
static ErrorCode | get_shared_vertices (ParallelComm *pcomm, ScdBox *box, std::vector< int > &procs, std::vector< int > &offsets, std::vector< int > &shared_indices) |
Get vertices shared with other processors. | |
static ErrorCode | get_indices (const int *const ldims, const int *const rdims, const int *const across_bdy, int *face_dims, std::vector< int > &shared_indices) |
static ErrorCode | get_neighbor_alljorkori (int np, int pfrom, const int *const gdims, const int *const gperiodic, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
static ErrorCode | get_neighbor_alljkbal (int np, int pfrom, const int *const gdims, const int *const gperiodic, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
static ErrorCode | get_neighbor_sqij (int np, int pfrom, const int *const gdims, const int *const gperiodic, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
static ErrorCode | get_neighbor_sqjk (int np, int pfrom, const int *const gdims, const int *const gperiodic, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
static ErrorCode | get_neighbor_sqijk (int np, int pfrom, const int *const gdims, const int *const gperiodic, const int *const dijk, int &pto, int *rdims, int *facedims, int *across_bdy) |
static int | gtol (const int *gijk, int i, int j, int k) |
Private Attributes | |
Interface * | mbImpl |
interface instance | |
bool | searchedBoxes |
whether we've searched the database for boxes yet | |
std::vector< ScdBox * > | scdBoxes |
structured mesh blocks; stored as ScdBox objects, can get sets from those | |
Tag | boxPeriodicTag |
tag representing whether box is periodic in i and j | |
Tag | boxDimsTag |
tag representing box lower and upper corners | |
Tag | globalBoxDimsTag |
tag representing global lower and upper corners | |
Tag | partMethodTag |
tag representing partition method | |
Tag | boxSetTag |
tag pointing from set to ScdBox | |
Friends | |
class | ScdBox |
A structured mesh interface for MOAB-based data.
Structured mesh in MOAB is created and accessed through the ScdInterface and ScdBox classes.
Structured mesh can be constructed in one of two ways. First, a rectangular block of mesh, both vertices and edges/quads/hexes, can be created in one shot, using the construct_box method. In this case, there are single sequences of vertices/entities. The second method for creating structured mesh is to create the structured blocks of vertices and elements separately. In this case, different blocks of elements can share blocks of vertices, and each block of elements has its own independent parametric space. The algorithms behind this representation are described in T. Tautges, "MOAB-SD: Integrated structured and unstructured mesh representation", Eng. w Comp, vol 20 no. 3.
Structured mesh is represented in MOAB down at the element sequence level, which is something applications don't see. In addition, when structured mesh is created, entity sets are also created and tagged with information about the parametric space. In particular, the BOX_DIMS tag is used to indicate the lower and upper corners in parametric space (this tag is integer size 6). Structured mesh blocks are also available through ScdBox class objects returned by ScdInterface. These class objects should be treated only as references to the structured mesh blocks; that is, the structured mesh referenced by these objects is not deleted when the ScdBox instance is destroyed. Functions for destroying the actual mesh are available on this class, though.
Structured mesh blocks are returned in the form of ScdBox class objects. Each ScdBox instance represents a rectangular block of vertices and possibly elements (edges, quads, or hexes). The edge/quad/hex entity handles for a ScdBox are guaranteed to be contiguous, starting at a starting value which is also available through the ScdBox class. However, vertex handles may or may not be contiguous, depending on the construction method. The start vertex handle is also available from the ScdBox class.
Each structured box has a parametric (ijk) space, which can be queried through the ScdBox interface. For non-periodic boxes, the edge/quad/hex parameter bounds are one less in each dimension than that of the vertices, otherwise they are the same as the vertex parameter bounds. In a parallel representation, boxes are locally non-periodic by default, but global ids are assigned such that the last set of vertices in a periodic direction match those of the first set of vertices in that direction.
Entity handles are allocated with the i parameter varying fastest, then j, then k.
Boxes can be periodic in i, or j, or both i and j. If only i or j is periodic, the corresponding mesh is a strip or an annular cylinder; if both i and j are periodic, the corresponding mesh is an annular torus. A box cannot be periodic in all three parameters. If i and/or j is periodic, and assuming IMIN/JMIN is zero, the parameter extents in the/each periodic direction (IMAX/JMAX) for vertices and edges/faces/hexes are the same, and the vertices on the "top" end in the periodic direction are at parameter value IMIN/JMIN.
For parallel structured meshes, each local mesh (the mesh on a given process) looks like a non-periodic structured mesh, and there are both local and global parameters of the structured mesh. If the mesh is periodic in a given direction, the last process in the periodic direction has local IMAX/JMAX that is one greater than the global IMAX/JMAX.
In parallel, the periodicity described in the previous paragraph is "local periodicity"; there is also the notion of global periodicity. For serial meshes, those concepts are the same. In parallel, a mesh can be locally non-periodic but globally periodic in a given direction. In that case, the local mesh is still non-periodic, i.e. the parametric extents for edges is one fewer than that of vertices in that direction. However, vertices are given global ids such that they match those of the parametric minimum in that direction. Geometric positions of the vertices at the high end should still be greater than the ones just below.
This interface supports parametric access to intermediate-dimension entities, e.g. adjacent faces and edges in a 3d mesh. In this case, a direction parameter is added, to identify the parametric direction of the entities being requested. For example, to retrieve the faces adjacent to a hex with parameters ijk, in the i parametric direction, you would use the parameters ijk0. These intermediate entities are not stored in a structured representation, but their parametric positions can be evaluated based on their adjacencies to higher-dimensional entities. Thanks to Milad Fatenejad for the thinking behind this.
The ScdBox class provides functions for evaluating the mesh based on the ijk parameter space. These functions are inlined where possible, for efficiency.
Definition at line 151 of file ScdInterface.hpp.
moab::ScdInterface::ScdInterface | ( | Interface * | impl, |
bool | find_boxes = false |
||
) |
Constructor.
Constructor; if find_boxes is true, this will search for entity sets marked as structured blocks, based on the BOX_DIMS tag. Structured mesh blocks will be stored in this interface class for future retrieval. Structured mesh blocks created through this interface will also be stored here.
impl | MOAB instance |
find_boxes | If true, search all the entity sets, caching the structured mesh blocks |
Definition at line 33 of file ScdInterface.cpp.
References find_boxes(), and scdBoxes.
: mbImpl( imp ), searchedBoxes( false ), boxPeriodicTag( 0 ), boxDimsTag( 0 ), globalBoxDimsTag( 0 ), partMethodTag( 0 ), boxSetTag( 0 ) { if( boxes ) find_boxes( scdBoxes ); }
Definition at line 41 of file ScdInterface.cpp.
References box_set_tag(), mbImpl, scdBoxes, and moab::Interface::tag_delete().
{ std::vector< ScdBox* > tmp_boxes; tmp_boxes.swap( scdBoxes ); for( std::vector< ScdBox* >::iterator rit = tmp_boxes.begin(); rit != tmp_boxes.end(); ++rit ) delete *rit; if( box_set_tag( false ) ) mbImpl->tag_delete( box_set_tag() ); }
ErrorCode moab::ScdInterface::add_box | ( | ScdBox * | box | ) | [protected] |
Add the box to the list on ScdInterface.
Definition at line 462 of file ScdInterface.cpp.
References MB_SUCCESS, and scdBoxes.
Referenced by moab::ScdBox::ScdBox().
{ scdBoxes.push_back( box ); return MB_SUCCESS; }
ErrorCode moab::ScdInterface::assign_global_ids | ( | ScdBox * | box | ) | [private] |
assign global ids to vertices in this box
Definition at line 252 of file ScdInterface.cpp.
References moab::ScdBox::box_dims(), ErrorCode, ERRORR, moab::ScdParData::gDims, moab::Interface::globalId_tag(), moab::ScdParData::gPeriodic, moab::ScdBox::locally_periodic(), MB_SUCCESS, mbImpl, moab::ScdBox::num_vertices(), moab::ScdBox::par_data(), moab::ScdBox::start_vertex(), and moab::Interface::tag_iterate().
Referenced by construct_box().
{ // Get a ptr to global id memory void* data; int count = 0; Tag gid_tag = mbImpl->globalId_tag(); Range tmp_range( box->start_vertex(), box->start_vertex() + box->num_vertices() ); ErrorCode rval = mbImpl->tag_iterate( gid_tag, tmp_range.begin(), tmp_range.end(), count, data );ERRORR( rval, "Failed to get tag iterator." ); assert( count == box->num_vertices() ); int* gid_data = (int*)data; int di = box->par_data().gDims[3] - box->par_data().gDims[0] + 1; int dj = box->par_data().gDims[4] - box->par_data().gDims[1] + 1; for( int kl = box->box_dims()[2]; kl <= box->box_dims()[5]; kl++ ) { for( int jl = box->box_dims()[1]; jl <= box->box_dims()[4]; jl++ ) { for( int il = box->box_dims()[0]; il <= box->box_dims()[3]; il++ ) { int itmp = ( !box->locally_periodic()[0] && box->par_data().gPeriodic[0] && il == box->par_data().gDims[3] ? box->par_data().gDims[0] : il ); *gid_data = ( -1 != kl ? kl * di * dj : 0 ) + jl * di + itmp + 1; gid_data++; } } } return MB_SUCCESS; }
Tag moab::ScdInterface::box_dims_tag | ( | bool | create_if_missing = true | ) |
Return the tag marking the lower and upper corners of boxes.
create_if_missing | If the tag does not yet exist, create it |
Definition at line 381 of file ScdInterface.cpp.
References boxDimsTag, ErrorCode, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TYPE_INTEGER, mbImpl, moab::Interface::tag_get_handle(), and moab::Interface::tag_get_name().
Referenced by create_box_set(), and find_boxes().
{ // Reset boxDimsTag in case it has been deleted (e.g. by clean_up_failed_read) if( boxDimsTag ) { std::string tag_name; if( MB_TAG_NOT_FOUND == mbImpl->tag_get_name( boxDimsTag, tag_name ) ) boxDimsTag = NULL; } if( boxDimsTag || !create_if_missing ) return boxDimsTag; ErrorCode rval = mbImpl->tag_get_handle( "BOX_DIMS", 6, MB_TYPE_INTEGER, boxDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != rval ) return 0; return boxDimsTag; }
Tag moab::ScdInterface::box_periodic_tag | ( | bool | create_if_missing = true | ) |
Return the tag marking whether box is periodic in i and j.
create_if_missing | If the tag does not yet exist, create it |
Definition at line 364 of file ScdInterface.cpp.
References boxPeriodicTag, ErrorCode, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TYPE_INTEGER, mbImpl, moab::Interface::tag_get_handle(), and moab::Interface::tag_get_name().
Referenced by create_box_set().
{ // Reset boxPeriodicTag in case it has been deleted (e.g. by Core::clean_up_failed_read) if( boxPeriodicTag ) { std::string tag_name; if( MB_TAG_NOT_FOUND == mbImpl->tag_get_name( boxPeriodicTag, tag_name ) ) boxPeriodicTag = NULL; } if( boxPeriodicTag || !create_if_missing ) return boxPeriodicTag; ErrorCode rval = mbImpl->tag_get_handle( "BOX_PERIODIC", 3, MB_TYPE_INTEGER, boxPeriodicTag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != rval ) return 0; return boxPeriodicTag; }
Tag moab::ScdInterface::box_set_tag | ( | bool | create_if_missing = true | ) |
Return the tag marking the ScdBox for a set.
create_if_missing | If the tag does not yet exist, create it |
Definition at line 431 of file ScdInterface.cpp.
References boxSetTag, ErrorCode, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TYPE_OPAQUE, mbImpl, moab::Interface::tag_get_handle(), and moab::Interface::tag_get_name().
Referenced by create_scd_sequence(), get_scd_box(), moab::ScdBox::~ScdBox(), and ~ScdInterface().
{ // Reset boxSetTag in case it has been deleted (e.g. by Core::clean_up_failed_read) if( boxSetTag ) { std::string tag_name; if( MB_TAG_NOT_FOUND == mbImpl->tag_get_name( boxSetTag, tag_name ) ) boxSetTag = NULL; } if( boxSetTag || !create_if_missing ) return boxSetTag; ErrorCode rval = mbImpl->tag_get_handle( "__BOX_SET", sizeof( ScdBox* ), MB_TYPE_OPAQUE, boxSetTag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != rval ) return 0; return boxSetTag; }
ErrorCode moab::ScdInterface::compute_partition | ( | int | np, |
int | nr, | ||
const ScdParData & | par_data, | ||
int * | ldims, | ||
int * | lperiodic = NULL , |
||
int * | pdims = NULL |
||
) | [inline, static] |
Compute a partition of structured parameter space.
Compute a partition of structured parameter space, based on data in the ScdParData passed in. Results are passed back in arguments, which application can set back into par_data argument if they so desire.
np | Number of processors |
nr | Rank of this processor |
par_data | ScdParData object that contains input global parameter space, desired partitioning method, and information about global periodicity. |
ldims | Local parameters for grid |
lperiodic | Whether or not a given dimension is locally periodic |
pdims | Number of procs in i, j, k directions |
Definition at line 849 of file ScdInterface.hpp.
References moab::ScdParData::ALLJKBAL, moab::ScdParData::ALLJORKORI, compute_partition_alljkbal(), compute_partition_alljorkori(), compute_partition_sqij(), compute_partition_sqijk(), compute_partition_sqjk(), ErrorCode, moab::ScdParData::gDims, moab::ScdParData::gPeriodic, MB_SUCCESS, moab::ScdParData::partMethod, moab::ScdParData::SQIJ, moab::ScdParData::SQIJK, and moab::ScdParData::SQJK.
Referenced by construct_box(), moab::NCHelperDomain::init_mesh_vals(), moab::NCHelperFV::init_mesh_vals(), moab::NCHelperEuler::init_mesh_vals(), test_parallel_partition(), and test_sqijk().
{ ErrorCode rval = MB_SUCCESS; switch( par_data.partMethod ) { case ScdParData::ALLJORKORI: case -1: rval = compute_partition_alljorkori( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims ); break; case ScdParData::ALLJKBAL: rval = compute_partition_alljkbal( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims ); break; case ScdParData::SQIJ: rval = compute_partition_sqij( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims ); break; case ScdParData::SQJK: rval = compute_partition_sqjk( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims ); break; case ScdParData::SQIJK: rval = compute_partition_sqijk( np, nr, par_data.gDims, par_data.gPeriodic, ldims, lperiodic, pdims ); break; default: rval = MB_FAILURE; break; } return rval; }
ErrorCode moab::ScdInterface::compute_partition_alljkbal | ( | int | np, |
int | nr, | ||
const int | gijk[6], | ||
const int *const | gperiodic, | ||
int * | lijk, | ||
int * | lperiodic, | ||
int * | pijk | ||
) | [inline, static, private] |
Compute a partition of structured parameter space.
Partitions the structured parametric space by partitioning j, and possibly k, seeking square regions of jk space For description of arguments, see ScdInterface::compute_partition.
Definition at line 983 of file ScdInterface.hpp.
References MB_SUCCESS, and np.
Referenced by compute_partition(), and get_neighbor_alljkbal().
{ int tmp_lp[3], tmp_pijk[3]; if( !lperiodic ) lperiodic = tmp_lp; if( !pijk ) pijk = tmp_pijk; for( int i = 0; i < 3; i++ ) lperiodic[i] = gperiodic[i]; if( np == 1 ) { if( ldims ) { ldims[0] = gijk[0]; ldims[3] = gijk[3]; ldims[1] = gijk[1]; ldims[4] = gijk[4]; ldims[2] = gijk[2]; ldims[5] = gijk[5]; } pijk[0] = pijk[1] = pijk[2] = 1; } else { // improved, possibly 2-d partition std::vector< double > kfactors; kfactors.push_back( 1 ); int K = gijk[5] - gijk[2]; for( int i = 2; i < K; i++ ) if( !( K % i ) && !( np % i ) ) kfactors.push_back( i ); kfactors.push_back( K ); // compute the ideal nj and nk int J = gijk[4] - gijk[1]; double njideal = sqrt( ( (double)( np * J ) ) / ( (double)K ) ); double nkideal = ( njideal * K ) / J; int nk, nj; if( nkideal < 1.0 ) { nk = 1; nj = np; } else { std::vector< double >::iterator vit = std::lower_bound( kfactors.begin(), kfactors.end(), nkideal ); if( vit == kfactors.begin() ) nk = 1; else nk = (int)*( --vit ); nj = np / nk; } int dk = K / nk; int dj = J / nj; ldims[2] = gijk[2] + ( nr % nk ) * dk; ldims[5] = ldims[2] + dk; int extra = J % nj; ldims[1] = gijk[1] + ( nr / nk ) * dj + std::min( nr / nk, extra ); ldims[4] = ldims[1] + dj + ( nr / nk < extra ? 1 : 0 ); ldims[0] = gijk[0]; ldims[3] = gijk[3]; if( gperiodic[1] && np > 1 ) { lperiodic[1] = 0; if( nr / nk == nj - 1 ) { ldims[1]++; } } pijk[0] = 1; pijk[1] = nj; pijk[2] = nk; } return MB_SUCCESS; }
ErrorCode moab::ScdInterface::compute_partition_alljorkori | ( | int | np, |
int | nr, | ||
const int | gijk[6], | ||
const int *const | gperiodic, | ||
int * | lijk, | ||
int * | lperiodic, | ||
int * | pijk | ||
) | [inline, static, private] |
Compute a partition of structured parameter space.
Partitions the structured parametric space by partitioning j, k, or i only. If j is greater than #procs, partition that, else k, else i. For description of arguments, see ScdInterface::compute_partition.
Definition at line 883 of file ScdInterface.hpp.
References MB_SUCCESS, and np.
Referenced by compute_partition(), and get_neighbor_alljorkori().
{ // partition *the elements* over the parametric space; 1d partition for now, in the j, k, or i // parameters int tmp_lp[3], tmp_pijk[3]; if( !lperiodic ) lperiodic = tmp_lp; if( !pijk ) pijk = tmp_pijk; for( int i = 0; i < 3; i++ ) lperiodic[i] = gperiodic[i]; if( np == 1 ) { if( ldims ) { ldims[0] = gijk[0]; ldims[3] = gijk[3]; ldims[1] = gijk[1]; ldims[4] = gijk[4]; ldims[2] = gijk[2]; ldims[5] = gijk[5]; } pijk[0] = pijk[1] = pijk[2] = 1; } else { if( gijk[4] - gijk[1] > np ) { // partition j over procs int dj = ( gijk[4] - gijk[1] ) / np; int extra = ( gijk[4] - gijk[1] ) % np; ldims[1] = gijk[1] + nr * dj + std::min( nr, extra ); ldims[4] = ldims[1] + dj + ( nr < extra ? 1 : 0 ); if( gperiodic[1] && np > 1 ) { lperiodic[1] = 0; ldims[4]++; } ldims[2] = gijk[2]; ldims[5] = gijk[5]; ldims[0] = gijk[0]; ldims[3] = gijk[3]; pijk[0] = pijk[2] = 1; pijk[1] = np; } else if( gijk[5] - gijk[2] > np ) { // partition k over procs int dk = ( gijk[5] - gijk[2] ) / np; int extra = ( gijk[5] - gijk[2] ) % np; ldims[2] = gijk[2] + nr * dk + std::min( nr, extra ); ldims[5] = ldims[2] + dk + ( nr < extra ? 1 : 0 ); ldims[1] = gijk[1]; ldims[4] = gijk[4]; ldims[0] = gijk[0]; ldims[3] = gijk[3]; pijk[0] = pijk[1] = 1; pijk[2] = np; } else if( gijk[3] - gijk[0] > np ) { // partition i over procs int di = ( gijk[3] - gijk[0] ) / np; int extra = ( gijk[3] - gijk[0] ) % np; ldims[0] = gijk[0] + nr * di + std::min( nr, extra ); ldims[3] = ldims[0] + di + ( nr < extra ? 1 : 0 ); if( gperiodic[0] && np > 1 ) { lperiodic[0] = 0; ldims[3]++; } ldims[2] = gijk[2]; ldims[5] = gijk[5]; ldims[1] = gijk[1]; ldims[4] = gijk[4]; pijk[1] = pijk[2] = 1; pijk[0] = np; } else { // Couldn't find a suitable partition... return MB_FAILURE; } } return MB_SUCCESS; }
ErrorCode moab::ScdInterface::compute_partition_sqij | ( | int | np, |
int | nr, | ||
const int | gijk[6], | ||
const int *const | gperiodic, | ||
int * | lijk, | ||
int * | lperiodic, | ||
int * | pijk | ||
) | [inline, static, private] |
Compute a partition of structured parameter space.
Partitions the structured parametric space by seeking square ij partitions For description of arguments, see ScdInterface::compute_partition.
Definition at line 1073 of file ScdInterface.hpp.
References MB_SUCCESS.
Referenced by compute_partition(), and get_neighbor_sqij().
{ int tmp_lp[3], tmp_pijk[3]; if( !lperiodic ) lperiodic = tmp_lp; if( !pijk ) pijk = tmp_pijk; // square IxJ partition for( int i = 0; i < 3; i++ ) lperiodic[i] = gperiodic[i]; if( np == 1 ) { if( ldims ) { ldims[0] = gijk[0]; ldims[3] = gijk[3]; ldims[1] = gijk[1]; ldims[4] = gijk[4]; ldims[2] = gijk[2]; ldims[5] = gijk[5]; } pijk[0] = pijk[1] = pijk[2] = 1; } else { std::vector< double > pfactors, ppfactors; for( int i = 2; i <= np / 2; i++ ) if( !( np % i ) ) { pfactors.push_back( i ); ppfactors.push_back( ( (double)( i * i ) ) / np ); } pfactors.push_back( np ); ppfactors.push_back( (double)np ); // ideally, Px/Py = I/J double ijratio = ( (double)( gijk[3] - gijk[0] ) ) / ( (double)( gijk[4] - gijk[1] ) ); unsigned int ind = 0; std::vector< double >::iterator optimal = std::lower_bound( ppfactors.begin(), ppfactors.end(), ijratio ); if( optimal == ppfactors.end() ) { ind = ppfactors.size() - 1; } else { ind = optimal - ppfactors.begin(); if( ind && fabs( ppfactors[ind - 1] - ijratio ) < fabs( ppfactors[ind] - ijratio ) ) ind--; } // VARIABLES DESCRIBING THE MESH: // pi, pj = # procs in i and j directions // nri, nrj = my proc's position in i, j directions // I, J = # edges/elements in i, j directions // iextra, jextra = # procs having extra edge in i/j direction // top_i, top_j = if true, I'm the last proc in the i/j direction // i, j = # edges locally in i/j direction, *not* including one for iextra/jextra int pi = pfactors[ind]; int pj = np / pi; int I = ( gijk[3] - gijk[0] ), J = ( gijk[4] - gijk[1] ); int iextra = I % pi, jextra = J % pj, i = I / pi, j = J / pj; int nri = nr % pi, nrj = nr / pi; if( ldims ) { ldims[0] = gijk[0] + i * nri + std::min( iextra, nri ); ldims[3] = ldims[0] + i + ( nri < iextra ? 1 : 0 ); ldims[1] = gijk[1] + j * nrj + std::min( jextra, nrj ); ldims[4] = ldims[1] + j + ( nrj < jextra ? 1 : 0 ); ldims[2] = gijk[2]; ldims[5] = gijk[5]; if( gperiodic[0] && pi > 1 ) { lperiodic[0] = 0; if( nri == pi - 1 ) ldims[3]++; } if( gperiodic[1] && pj > 1 ) { lperiodic[1] = 0; if( nrj == pj - 1 ) ldims[4]++; } } pijk[0] = pi; pijk[1] = pj; pijk[2] = 1; } return MB_SUCCESS; }
ErrorCode moab::ScdInterface::compute_partition_sqijk | ( | int | np, |
int | nr, | ||
const int | gijk[6], | ||
const int *const | gperiodic, | ||
int * | lijk, | ||
int * | lperiodic, | ||
int * | pijk | ||
) | [inline, static, private] |
Compute a partition of structured parameter space.
Partitions the structured parametric space by seeking square ijk partitions For description of arguments, see ScdInterface::compute_partition.
Definition at line 1261 of file ScdInterface.hpp.
References MB_SUCCESS, and np.
Referenced by compute_partition(), and get_neighbor_sqijk().
{ if( gperiodic[0] || gperiodic[1] || gperiodic[2] ) return MB_FAILURE; int tmp_lp[3], tmp_pijk[3]; if( !lperiodic ) lperiodic = tmp_lp; if( !pijk ) pijk = tmp_pijk; // square IxJxK partition for( int i = 0; i < 3; i++ ) lperiodic[i] = gperiodic[i]; if( np == 1 ) { if( ldims ) for( int i = 0; i < 6; i++ ) ldims[i] = gijk[i]; pijk[0] = pijk[1] = pijk[2] = 1; return MB_SUCCESS; } std::vector< int > pfactors; pfactors.push_back( 1 ); for( int i = 2; i <= np / 2; i++ ) if( !( np % i ) ) pfactors.push_back( i ); pfactors.push_back( np ); // test for IJ, JK, IK int IJK[3], dIJK[3]; for( int i = 0; i < 3; i++ ) IJK[i] = std::max( gijk[3 + i] - gijk[i], 1 ); // order IJK from lo to hi int lo = 0, hi = 0; for( int i = 1; i < 3; i++ ) { if( IJK[i] < IJK[lo] ) lo = i; if( IJK[i] > IJK[hi] ) hi = i; } if( lo == hi ) hi = ( lo + 1 ) % 3; int mid = 3 - lo - hi; // search for perfect subdivision of np that balances #cells int perfa_best = -1, perfb_best = -1; double ratio = 0.0; for( int po = 0; po < (int)pfactors.size(); po++ ) { for( int pi = po; pi < (int)pfactors.size() && np / ( pfactors[po] * pfactors[pi] ) >= pfactors[pi]; pi++ ) { int p3 = std::find( pfactors.begin(), pfactors.end(), np / ( pfactors[po] * pfactors[pi] ) ) - pfactors.begin(); if( p3 == (int)pfactors.size() || pfactors[po] * pfactors[pi] * pfactors[p3] != np ) continue; // po*pi should exactly factor np assert( po <= pi && pi <= p3 ); // by definition, po <= pi <= p3 double minl = std::min( std::min( IJK[lo] / pfactors[po], IJK[mid] / pfactors[pi] ), IJK[hi] / pfactors[p3] ), maxl = std::max( std::max( IJK[lo] / pfactors[po], IJK[mid] / pfactors[pi] ), IJK[hi] / pfactors[p3] ); if( minl / maxl > ratio ) { ratio = minl / maxl; perfa_best = po; perfb_best = pi; } } } if( perfa_best == -1 || perfb_best == -1 ) return MB_FAILURE; // VARIABLES DESCRIBING THE MESH: // pijk[i] = # procs in direction i // numr[i] = my proc's position in direction i // dIJK[i] = # edges/elements in direction i // extra[i]= # procs having extra edge in direction i // top[i] = if true, I'm the last proc in direction i pijk[lo] = pfactors[perfa_best]; pijk[mid] = pfactors[perfb_best]; pijk[hi] = ( np / ( pfactors[perfa_best] * pfactors[perfb_best] ) ); int extra[3] = { 0, 0, 0 }, numr[3]; for( int i = 0; i < 3; i++ ) { dIJK[i] = IJK[i] / pijk[i]; extra[i] = IJK[i] % pijk[i]; } numr[2] = nr / ( pijk[0] * pijk[1] ); int rem = nr % ( pijk[0] * pijk[1] ); numr[1] = rem / pijk[0]; numr[0] = rem % pijk[0]; for( int i = 0; i < 3; i++ ) { extra[i] = IJK[i] % dIJK[i]; ldims[i] = gijk[i] + numr[i] * dIJK[i] + std::min( extra[i], numr[i] ); ldims[3 + i] = ldims[i] + dIJK[i] + ( numr[i] < extra[i] ? 1 : 0 ); } return MB_SUCCESS; }
ErrorCode moab::ScdInterface::compute_partition_sqjk | ( | int | np, |
int | nr, | ||
const int | gijk[6], | ||
const int *const | gperiodic, | ||
int * | lijk, | ||
int * | lperiodic, | ||
int * | pijk | ||
) | [inline, static, private] |
Compute a partition of structured parameter space.
Partitions the structured parametric space by seeking square jk partitions For description of arguments, see ScdInterface::compute_partition.
Definition at line 1174 of file ScdInterface.hpp.
References MB_SUCCESS, and np.
Referenced by compute_partition(), and get_neighbor_sqjk().
{ int tmp_lp[3], tmp_pijk[3]; if( !lperiodic ) lperiodic = tmp_lp; if( !pijk ) pijk = tmp_pijk; // square JxK partition for( int i = 0; i < 3; i++ ) lperiodic[i] = gperiodic[i]; if( np == 1 ) { if( ldims ) { ldims[0] = gijk[0]; ldims[3] = gijk[3]; ldims[1] = gijk[1]; ldims[4] = gijk[4]; ldims[2] = gijk[2]; ldims[5] = gijk[5]; } pijk[0] = pijk[1] = pijk[2] = 1; } else { std::vector< double > pfactors, ppfactors; for( int p = 2; p <= np; p++ ) if( !( np % p ) ) { pfactors.push_back( p ); ppfactors.push_back( ( (double)( p * p ) ) / np ); } // ideally, Pj/Pk = J/K int pj, pk; if( gijk[5] == gijk[2] ) { pk = 1; pj = np; } else { double jkratio = ( (double)( gijk[4] - gijk[1] ) ) / ( (double)( gijk[5] - gijk[2] ) ); std::vector< double >::iterator vit = std::lower_bound( ppfactors.begin(), ppfactors.end(), jkratio ); if( vit == ppfactors.end() ) --vit; else if( vit != ppfactors.begin() && fabs( *( vit - 1 ) - jkratio ) < fabs( ( *vit ) - jkratio ) ) --vit; int ind = vit - ppfactors.begin(); pj = 1; if( ind >= 0 && !pfactors.empty() ) pfactors[ind]; pk = np / pj; } int K = ( gijk[5] - gijk[2] ), J = ( gijk[4] - gijk[1] ); int jextra = J % pj, kextra = K % pk, j = J / pj, k = K / pk; int nrj = nr % pj, nrk = nr / pj; ldims[1] = gijk[1] + j * nrj + std::min( jextra, nrj ); ldims[4] = ldims[1] + j + ( nrj < jextra ? 1 : 0 ); ldims[2] = gijk[2] + k * nrk + std::min( kextra, nrk ); ldims[5] = ldims[2] + k + ( nrk < kextra ? 1 : 0 ); ldims[0] = gijk[0]; ldims[3] = gijk[3]; if( gperiodic[1] && pj > 1 ) { lperiodic[1] = 0; if( nrj == pj - 1 ) ldims[4]++; } pijk[0] = 1; pijk[1] = pj; pijk[2] = pk; } return MB_SUCCESS; }
ErrorCode moab::ScdInterface::construct_box | ( | HomCoord | low, |
HomCoord | high, | ||
const double *const | coords, | ||
unsigned int | num_coords, | ||
ScdBox *& | new_box, | ||
int *const | lperiodic = NULL , |
||
ScdParData *const | par_data = NULL , |
||
bool | assign_global_ids = false , |
||
int | resolve_shared_ents = -1 |
||
) |
Construct new structured mesh box, including both vertices and elements.
Parameter range for vertex box is [low-high], for elements is [low-high). Construct quads by passing in low[2] == high[2], and edges by passing in low[1] == high[1] and low[2] == high[2]. The result is passed back in a ScdBox*, which is a *reference* to the box of structured mesh. That is, the actual mesh is retained in MOAB when the ScdBox is destroyed. To actually destroy the mesh, call the destroy_mesh function on the ScdBox object first, before destroying it.
low | Lower corner in parameter space |
high | Higher corner in parameter space |
coords | Coordinates of vertices, interleaved (xyzxyz...); if NULL, coords are set to parametric values |
num_coords | Number of coordinate values |
new_box | Reference to box of structured mesh |
lperiodic[3] | If lperiodic[s] != 0, direction s is locally periodic |
par_data | If non-NULL, this will get stored on the ScdBox once created, contains info about global parallel nature of ScdBox across procs |
assign_global_ids | If true, assigns 1-based global ids to vertices using GLOBAL_ID_TAG_NAME |
resolve_shared_ents | If != -1, resolves shared entities up to and including dimension equal to value |
Definition at line 112 of file ScdInterface.cpp.
References moab::Interface::add_entities(), moab::ScdBox::add_vbox(), assign_global_ids(), moab::ScdBox::box_set(), moab::ScdBox::box_size(), compute_partition(), moab::SequenceManager::create_scd_sequence(), create_scd_sequence(), moab::ScdBox::elem_seq(), ErrorCode, ERRORR, moab::ScdBox::get_coordinate_arrays(), moab::ParallelComm::get_debug_verbosity(), moab::ParallelComm::get_pcomm(), MB_SUCCESS, mbcore, MBEDGE, MBHEX, mbImpl, MBQUAD, MBVERTEX, MPI_COMM_WORLD, moab::ScdParData::NOPART, moab::ScdBox::num_elements(), moab::ScdBox::par_data(), moab::ScdParData::partMethod, moab::ScdParData::pComm, moab::ScdParData::pDims, moab::ParallelComm::rank(), moab::Core::sequence_manager(), moab::HomCoord::set(), moab::ParallelComm::size(), moab::ScdBox::start_element(), and tag_shared_vertices().
Referenced by create_hex_mesh(), moab::ScdNCHelper::create_mesh(), create_parallel_mesh(), iMesh_createStructuredMesh(), main(), mb_skin_scd_test(), test_bound_box(), test_periodic_seq(), and test_scd_invalid().
{ // create a rectangular structured mesh block ErrorCode rval; int tmp_lper[3] = { 0, 0, 0 }; if( lperiodic ) std::copy( lperiodic, lperiodic + 3, tmp_lper ); #ifndef MOAB_HAVE_MPI if( -1 != tag_shared_ents ) ERRORR( MB_FAILURE, "Parallel capability requested but MOAB not compiled parallel." ); if( -1 == tag_shared_ents && !assign_gids ) assign_gids = true; // need to assign gids in order to tag shared verts #else if( par_data && low == high && ScdParData::NOPART != par_data->partMethod ) { // requesting creation of parallel mesh, so need to compute partition if( !par_data->pComm ) { // this is a really boneheaded way to have to create a PC par_data->pComm = ParallelComm::get_pcomm( mbImpl, 0 ); if( NULL == par_data->pComm ) par_data->pComm = new ParallelComm( mbImpl, MPI_COMM_WORLD ); } int ldims[6]; rval = compute_partition( par_data->pComm->size(), par_data->pComm->rank(), *par_data, ldims, tmp_lper, par_data->pDims );ERRORR( rval, "Error returned from compute_partition." ); low.set( ldims[0], ldims[1], ldims[2] ); high.set( ldims[3], ldims[4], ldims[5] ); if( par_data->pComm->get_debug_verbosity() > 0 ) { std::cout << "Proc " << par_data->pComm->rank() << ": " << *par_data; std::cout << "Proc " << par_data->pComm->rank() << " local dims: " << low << "-" << high << std::endl; } } #endif HomCoord tmp_size = high - low + HomCoord( 1, 1, 1, 0 ); if( ( tmp_size[1] && num_coords && (int)num_coords < tmp_size[0] ) || ( tmp_size[2] && num_coords && (int)num_coords < tmp_size[0] * tmp_size[1] ) ) return MB_FAILURE; rval = create_scd_sequence( low, high, MBVERTEX, 0, new_box );ERRORR( rval, "Trouble creating scd vertex sequence." ); // set the vertex coordinates double *xc, *yc, *zc; rval = new_box->get_coordinate_arrays( xc, yc, zc );ERRORR( rval, "Couldn't get vertex coordinate arrays." ); if( coords && num_coords ) { unsigned int i = 0; for( int kl = low[2]; kl <= high[2]; kl++ ) { for( int jl = low[1]; jl <= high[1]; jl++ ) { for( int il = low[0]; il <= high[0]; il++ ) { xc[i] = coords[3 * i]; if( new_box->box_size()[1] ) yc[i] = coords[3 * i + 1]; if( new_box->box_size()[2] ) zc[i] = coords[3 * i + 2]; i++; } } } } else { unsigned int i = 0; for( int kl = low[2]; kl <= high[2]; kl++ ) { for( int jl = low[1]; jl <= high[1]; jl++ ) { for( int il = low[0]; il <= high[0]; il++ ) { xc[i] = (double)il; if( new_box->box_size()[1] ) yc[i] = (double)jl; else yc[i] = 0.0; if( new_box->box_size()[2] ) zc[i] = (double)kl; else zc[i] = 0.0; i++; } } } } // create element sequence Core* mbcore = dynamic_cast< Core* >( mbImpl ); SequenceManager* seq_mgr = mbcore->sequence_manager(); EntitySequence* tmp_seq; EntityHandle start_ent; // construct the sequence EntityType this_tp = MBHEX; if( 1 >= tmp_size[2] ) this_tp = MBQUAD; if( 1 >= tmp_size[2] && 1 >= tmp_size[1] ) this_tp = MBEDGE; rval = seq_mgr->create_scd_sequence( low, high, this_tp, 0, start_ent, tmp_seq, tmp_lper );ERRORR( rval, "Trouble creating scd element sequence." ); new_box->elem_seq( tmp_seq ); new_box->start_element( start_ent ); // add vertex seq to element seq, forward orientation, unity transform rval = new_box->add_vbox( new_box, // p1: imin,jmin low, low, // p2: imax,jmin low + HomCoord( 1, 0, 0 ), low + HomCoord( 1, 0, 0 ), // p3: imin,jmax low + HomCoord( 0, 1, 0 ), low + HomCoord( 0, 1, 0 ) );ERRORR( rval, "Error constructing structured element sequence." ); // add the new hexes to the scd box set; vertices were added in call to create_scd_sequence Range tmp_range( new_box->start_element(), new_box->start_element() + new_box->num_elements() - 1 ); rval = mbImpl->add_entities( new_box->box_set(), tmp_range );ERRORR( rval, "Couldn't add new hexes to box set." ); if( par_data ) new_box->par_data( *par_data ); if( assign_gids ) { rval = assign_global_ids( new_box );ERRORR( rval, "Trouble assigning global ids" ); } #ifdef MOAB_HAVE_MPI if( par_data && -1 != tag_shared_ents ) { rval = tag_shared_vertices( par_data->pComm, new_box ); } #endif return MB_SUCCESS; }
ErrorCode moab::ScdInterface::create_box_set | ( | const HomCoord & | low, |
const HomCoord & | high, | ||
EntityHandle & | scd_set, | ||
int * | is_periodic = NULL |
||
) | [private] |
Create an entity set for a box, and tag with the parameters.
low | Lower corner parameters for this box |
high | Upper corner parameters for this box |
scd_set | Entity set created |
is_periodic[3] | If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1,2]) |
Definition at line 337 of file ScdInterface.cpp.
References box_dims_tag(), box_periodic_tag(), moab::Interface::create_meshset(), ErrorCode, MB_SUCCESS, mbImpl, MESHSET_SET, and moab::Interface::tag_set_data().
Referenced by create_scd_sequence().
{ // create the set and put the entities in it ErrorCode rval = mbImpl->create_meshset( MESHSET_SET, scd_set ); if( MB_SUCCESS != rval ) return rval; // tag the set with parameter extents int boxdims[6]; for( int i = 0; i < 3; i++ ) boxdims[i] = low[i]; for( int i = 0; i < 3; i++ ) boxdims[3 + i] = high[i]; rval = mbImpl->tag_set_data( box_dims_tag(), &scd_set, 1, boxdims ); if( MB_SUCCESS != rval ) return rval; if( is_periodic ) { rval = mbImpl->tag_set_data( box_periodic_tag(), &scd_set, 1, is_periodic ); if( MB_SUCCESS != rval ) return rval; } return rval; }
ErrorCode moab::ScdInterface::create_scd_sequence | ( | const HomCoord & | low, |
const HomCoord & | high, | ||
EntityType | type, | ||
int | starting_id, | ||
ScdBox *& | new_box, | ||
int * | is_periodic = NULL |
||
) |
Create a structured sequence of vertices, quads, or hexes.
Starting handle for the sequence is available from the returned ScdBox. If creating a structured quad or hex box, subsequent calls must be made to ScdBox::add_vbox, until all the vertices have been filled in for the box.
low | Lower corner of structured box |
high | Higher corner of structured box |
type | EntityType, one of MBVERTEX, MBEDGE, MBQUAD, MBHEX |
starting_id | Requested start id of entities |
new_box | Reference to the newly created box of entities |
is_periodic[3] | If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1,2]) |
Definition at line 284 of file ScdInterface.cpp.
References moab::Interface::add_entities(), box_set_tag(), create_box_set(), moab::SequenceManager::create_scd_sequence(), ErrorCode, moab::Range::insert(), MB_SUCCESS, MB_TYPE_OUT_OF_RANGE, mbcore, MBEDGE, MBHEX, mbImpl, MBQUAD, MBVERTEX, moab::ScdBox::num_elements(), moab::ScdBox::num_vertices(), ScdBox, moab::Core::sequence_manager(), and moab::Interface::tag_set_data().
Referenced by construct_box(), create_1d_3_sequences(), create_2d_3_sequences(), create_2dtri_3_sequences(), create_3dtri_3_sequences(), eseq_test1a(), eseq_test1b(), eseq_test1c(), and test_vertex_seq().
{ HomCoord tmp_size = high - low + HomCoord( 1, 1, 1, 0 ); if( ( tp == MBHEX && 1 >= tmp_size[2] ) || ( tp == MBQUAD && 1 >= tmp_size[1] ) || ( tp == MBEDGE && 1 >= tmp_size[0] ) ) return MB_TYPE_OUT_OF_RANGE; Core* mbcore = dynamic_cast< Core* >( mbImpl ); assert( mbcore != NULL ); SequenceManager* seq_mgr = mbcore->sequence_manager(); EntitySequence* tmp_seq; EntityHandle start_ent, scd_set; // construct the sequence ErrorCode rval = seq_mgr->create_scd_sequence( low, high, tp, starting_id, start_ent, tmp_seq, is_periodic ); if( MB_SUCCESS != rval ) return rval; // create the set for this rectangle rval = create_box_set( low, high, scd_set ); if( MB_SUCCESS != rval ) return rval; // make the ScdBox new_box = new ScdBox( this, scd_set, tmp_seq ); if( !new_box ) return MB_FAILURE; // set the start vertex/element Range new_range; if( MBVERTEX == tp ) { new_range.insert( start_ent, start_ent + new_box->num_vertices() - 1 ); } else { new_range.insert( start_ent, start_ent + new_box->num_elements() - 1 ); } // put the entities in the box set rval = mbImpl->add_entities( scd_set, new_range ); if( MB_SUCCESS != rval ) return rval; // tag the set with the box rval = mbImpl->tag_set_data( box_set_tag(), &scd_set, 1, &new_box ); if( MB_SUCCESS != rval ) return rval; return MB_SUCCESS; }
ErrorCode moab::ScdInterface::find_boxes | ( | std::vector< ScdBox * > & | boxes | ) |
Return all the structured mesh blocks in this MOAB instance, as ScdBox objects.
Return the structured blocks in this MOAB instance. If these were not searched for at instantiation time, then the search is done now.
boxes | Vector of ScdBox objects representing structured mesh blocks |
Definition at line 57 of file ScdInterface.cpp.
References moab::Range::begin(), moab::Range::end(), ErrorCode, get_scd_box(), and MB_SUCCESS.
Referenced by moab::HalfFacetRep::check_mixed_entity_type(), moab::Skinner::find_skin_scd(), and ScdInterface().
{ Range tmp_boxes; ErrorCode rval = find_boxes( tmp_boxes ); if( MB_SUCCESS != rval ) return rval; for( Range::iterator rit = tmp_boxes.begin(); rit != tmp_boxes.end(); ++rit ) { ScdBox* tmp_box = get_scd_box( *rit ); if( tmp_box ) scd_boxes.push_back( tmp_box ); else rval = MB_FAILURE; } return rval; }
ErrorCode moab::ScdInterface::find_boxes | ( | Range & | boxes | ) |
Return all the structured mesh blocks in this MOAB instance, as entity set handles.
Return the structured blocks in this MOAB instance. If these were not searched for at instantiation time, then the search is done now.
boxes | Range of entity set objects representing structured mesh blocks |
Definition at line 75 of file ScdInterface.cpp.
References box_dims_tag(), boxDimsTag, boxSetTag, moab::dum, moab::Range::empty(), ErrorCode, moab::Interface::get_entities_by_type_and_tag(), moab::Range::insert(), MB_SUCCESS, MBENTITYSET, mbImpl, scdBoxes, searchedBoxes, moab::Range::size(), moab::Interface::tag_get_data(), and moab::Interface::UNION.
{ ErrorCode rval = MB_SUCCESS; box_dims_tag(); Range boxes; if( !searchedBoxes ) { rval = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &boxDimsTag, NULL, 1, boxes, Interface::UNION ); searchedBoxes = true; if( !boxes.empty() ) { scdBoxes.resize( boxes.size() ); rval = mbImpl->tag_get_data( boxSetTag, boxes, &scdBoxes[0] ); ScdBox* dum = NULL; // std::remove_if(scdBoxes.begin(), scdBoxes.end(), // std::bind2nd(std::equal_to<ScdBox*>(), dum) ) ; std::remove_if( scdBoxes.begin(), scdBoxes.end(), std::bind( std::equal_to< ScdBox* >(), std::placeholders::_1, dum ) ); // https://stackoverflow.com/questions/32739018/a-replacement-for-stdbind2nd } } for( std::vector< ScdBox* >::iterator vit = scdBoxes.begin(); vit != scdBoxes.end(); ++vit ) scd_boxes.insert( ( *vit )->box_set() ); return rval; }
ErrorCode moab::ScdInterface::get_boxes | ( | std::vector< ScdBox * > & | boxes | ) |
Return all the structured mesh blocks known by ScdInterface (does not search)
Return the structured blocks in this ScdInterface instance. Does not search for new boxes, just returns the contents of the list.
boxes | Structured boxes |
Definition at line 468 of file ScdInterface.cpp.
References MB_SUCCESS, and scdBoxes.
{ std::copy( scdBoxes.begin(), scdBoxes.end(), std::back_inserter( boxes ) ); return MB_SUCCESS; }
ErrorCode moab::ScdInterface::get_indices | ( | const int *const | ldims, |
const int *const | rdims, | ||
const int *const | across_bdy, | ||
int * | face_dims, | ||
std::vector< int > & | shared_indices | ||
) | [inline, static, private] |
Definition at line 1371 of file ScdInterface.hpp.
References gtol(), and MB_SUCCESS.
Referenced by get_shared_vertices().
{ // check for going across periodic bdy and face_dims not in my ldims (I'll always be on top in // that case)... if( across_bdy[0] > 0 && face_dims[0] != ldims[3] ) face_dims[0] = face_dims[3] = ldims[3]; else if( across_bdy[0] < 0 && face_dims[0] != ldims[0] ) face_dims[0] = face_dims[3] = ldims[0]; if( across_bdy[1] > 0 && face_dims[1] != ldims[4] ) face_dims[1] = face_dims[4] = ldims[4]; else if( across_bdy[1] < 0 && face_dims[1] != ldims[1] ) face_dims[0] = face_dims[3] = ldims[1]; for( int k = face_dims[2]; k <= face_dims[5]; k++ ) for( int j = face_dims[1]; j <= face_dims[4]; j++ ) for( int i = face_dims[0]; i <= face_dims[3]; i++ ) shared_indices.push_back( gtol( ldims, i, j, k ) ); if( across_bdy[0] > 0 && face_dims[0] != rdims[0] ) face_dims[0] = face_dims[3] = rdims[0]; else if( across_bdy[0] < 0 && face_dims[0] != rdims[3] ) face_dims[0] = face_dims[3] = rdims[3]; if( across_bdy[1] > 0 && face_dims[1] != rdims[1] ) face_dims[1] = face_dims[4] = rdims[1]; else if( across_bdy[1] < 0 && face_dims[1] != rdims[4] ) face_dims[0] = face_dims[3] = rdims[4]; for( int k = face_dims[2]; k <= face_dims[5]; k++ ) for( int j = face_dims[1]; j <= face_dims[4]; j++ ) for( int i = face_dims[0]; i <= face_dims[3]; i++ ) shared_indices.push_back( gtol( rdims, i, j, k ) ); return MB_SUCCESS; }
ErrorCode moab::ScdInterface::get_neighbor | ( | int | np, |
int | nr, | ||
const ScdParData & | spd, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [inline, static] |
Get information about the neighbor in the dijk[] direction, where dijk can be -1 or 1 for all 3 params Get information about the neighbor in the dijk[] direction, where dijk can be -1 or 1 for all 3 params
np | (in) Total # procs |
nr | Processor from which neighbor is requested |
spd | (in) ScdParData containing part method, gdims, gperiodic data |
dijk(*) | (in) Direction being queried, = +/-1 or 0 |
pto | (out) Processor holding the destination part |
rdims(6) | (out) Parametric min/max of destination part |
facedims(6) | (out) Parametric min/max of interface between pfrom and pto; if at the max in a periodic direction, set to global min of that direction |
across_bdy(3) | (out) If across_bdy[i] is -1(1), interface with pto is across periodic lower(upper) bdy in parameter i, 0 otherwise |
Definition at line 1410 of file ScdInterface.hpp.
References moab::ScdParData::ALLJKBAL, moab::ScdParData::ALLJORKORI, moab::ScdParData::gDims, get_neighbor_alljkbal(), get_neighbor_alljorkori(), get_neighbor_sqij(), get_neighbor_sqijk(), get_neighbor_sqjk(), moab::ScdParData::gPeriodic, MB_SUCCESS, moab::ScdParData::partMethod, moab::ScdParData::SQIJ, moab::ScdParData::SQIJK, and moab::ScdParData::SQJK.
Referenced by get_shared_vertices(), and test_parallel_partition().
{ if( !dijk[0] && !dijk[1] && !dijk[2] ) { // not going anywhere, return pto = -1; return MB_SUCCESS; } switch( spd.partMethod ) { case ScdParData::ALLJORKORI: case -1: return get_neighbor_alljorkori( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy ); case ScdParData::ALLJKBAL: return get_neighbor_alljkbal( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy ); case ScdParData::SQIJ: return get_neighbor_sqij( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy ); case ScdParData::SQJK: return get_neighbor_sqjk( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy ); case ScdParData::SQIJK: return get_neighbor_sqijk( np, pfrom, spd.gDims, spd.gPeriodic, dijk, pto, rdims, facedims, across_bdy ); default: break; } return MB_FAILURE; }
ErrorCode moab::ScdInterface::get_neighbor_alljkbal | ( | int | np, |
int | pfrom, | ||
const int *const | gdims, | ||
const int *const | gperiodic, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [static, private] |
Definition at line 861 of file ScdInterface.cpp.
References compute_partition_alljkbal(), ErrorCode, MB_SUCCESS, and np.
Referenced by get_neighbor().
{ if( dijk[0] != 0 ) { pto = -1; return MB_SUCCESS; } pto = -1; across_bdy[0] = across_bdy[1] = across_bdy[2] = 0; int ldims[6], pijk[3], lperiodic[3]; ErrorCode rval = compute_partition_alljkbal( np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk ); if( MB_SUCCESS != rval ) return rval; assert( pijk[1] * pijk[2] == np ); pto = -1; bool bot_j = pfrom< pijk[2], top_j = pfrom > np - pijk[2]; if( ( 1 == pijk[2] && dijk[2] ) || // 1d in j means no neighbors with dk != 0 ( !( pfrom % pijk[2] ) && -1 == dijk[2] ) || // at -k bdy ( pfrom % pijk[2] == pijk[2] - 1 && 1 == dijk[2] ) || // at +k bdy ( pfrom < pijk[2] && -1 == dijk[1] && !gperiodic[1] ) || // down and not periodic ( pfrom >= np - pijk[2] && 1 == dijk[1] && !gperiodic[1] ) ) // up and not periodic return MB_SUCCESS; pto = pfrom; std::copy( ldims, ldims + 6, rdims ); std::copy( ldims, ldims + 6, facedims ); if( 0 != dijk[1] ) { pto = ( pto + dijk[1] * pijk[2] + np ) % np; assert( pto >= 0 && pto < np ); int dj = ( gdims[4] - gdims[1] ) / pijk[1], extra = ( gdims[4] - gdims[1] ) % pijk[1]; if( -1 == dijk[1] ) { facedims[4] = facedims[1]; if( bot_j ) { // going across periodic lower bdy in j rdims[4] = gdims[4]; across_bdy[1] = -1; } else { rdims[4] = ldims[1]; } rdims[1] = rdims[4] - dj; if( pto < extra ) rdims[1]--; } else { if( pfrom > np - pijk[2] ) facedims[4] = gdims[1]; facedims[1] = facedims[4]; if( top_j ) { // going across periodic upper bdy in j rdims[1] = gdims[1]; across_bdy[1] = 1; } else { rdims[1] = ldims[4]; } rdims[4] = rdims[1] + dj; if( pto < extra ) rdims[4]++; } } if( 0 != dijk[2] ) { pto = ( pto + dijk[2] ) % np; assert( pto >= 0 && pto < np ); facedims[2] = facedims[5] = ( -1 == dijk[2] ? facedims[2] : facedims[5] ); int dk = ( gdims[5] - gdims[2] ) / pijk[2]; if( -1 == dijk[2] ) { facedims[5] = facedims[2]; rdims[5] = ldims[2]; rdims[2] = rdims[5] - dk; // never any kextra for alljkbal } else { facedims[2] = facedims[5]; rdims[2] = ldims[5]; rdims[5] = rdims[2] + dk; // never any kextra for alljkbal } } assert( -1 == pto || ( rdims[0] >= gdims[0] && rdims[3] <= gdims[3] ) ); assert( -1 == pto || ( rdims[1] >= gdims[1] && ( rdims[4] <= gdims[4] || ( across_bdy[1] && bot_j ) ) ) ); assert( -1 == pto || ( rdims[2] >= gdims[2] && rdims[5] <= gdims[5] ) ); assert( -1 == pto || ( ( facedims[0] >= rdims[0] || ( gperiodic[0] && rdims[3] == gdims[3] + 1 && facedims[0] == gdims[0] ) ) ) ); assert( -1 == pto || ( facedims[3] <= rdims[3] ) ); assert( -1 == pto || ( ( facedims[1] >= rdims[1] || ( gperiodic[1] && rdims[4] == gdims[4] + 1 && facedims[1] == gdims[1] ) ) ) ); assert( -1 == pto || ( facedims[4] <= rdims[4] ) ); assert( -1 == pto || ( facedims[2] >= rdims[2] ) ); assert( -1 == pto || ( facedims[5] <= rdims[5] ) ); assert( -1 == pto || ( facedims[0] >= ldims[0] ) ); assert( -1 == pto || ( facedims[3] <= ldims[3] ) ); assert( -1 == pto || ( facedims[1] >= ldims[1] ) ); assert( -1 == pto || ( facedims[4] <= ldims[4] ) ); assert( -1 == pto || ( facedims[2] >= ldims[2] ) ); assert( -1 == pto || ( facedims[5] <= ldims[5] ) ); return MB_SUCCESS; }
ErrorCode moab::ScdInterface::get_neighbor_alljorkori | ( | int | np, |
int | pfrom, | ||
const int *const | gdims, | ||
const int *const | gperiodic, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [static, private] |
Definition at line 1341 of file ScdInterface.cpp.
References compute_partition_alljorkori(), ErrorCode, and MB_SUCCESS.
Referenced by get_neighbor().
{ ErrorCode rval = MB_SUCCESS; pto = -1; if( np == 1 ) return MB_SUCCESS; int pijk[3], lperiodic[3], ldims[6]; rval = compute_partition_alljorkori( np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk ); if( MB_SUCCESS != rval ) return rval; int ind = -1; across_bdy[0] = across_bdy[1] = across_bdy[2] = 0; for( int i = 0; i < 3; i++ ) { if( pijk[i] > 1 ) { ind = i; break; } } assert( -1 < ind ); if( !dijk[ind] ) // no neighbor, pto is already -1, return return MB_SUCCESS; bool is_periodic = ( ( gperiodic[0] && ind == 0 ) || ( gperiodic[1] && ind == 1 ) ); if( dijk[( ind + 1 ) % 3] || dijk[( ind + 2 ) % 3] || // stepping in either other two directions ( !is_periodic && ldims[ind] == gdims[ind] && dijk[ind] == -1 ) || // lower side and going lower ( !is_periodic && ldims[3 + ind] >= gdims[3 + ind] && dijk[ind] == 1 ) ) // not >= because ldims is only > gdims when periodic; // higher side and going higher return MB_SUCCESS; std::copy( ldims, ldims + 6, facedims ); std::copy( ldims, ldims + 6, rdims ); int dind = ( gdims[ind + 3] - gdims[ind] ) / np; int extra = ( gdims[ind + 3] - gdims[ind] ) % np; if( -1 == dijk[ind] && pfrom ) { // actual left neighbor pto = pfrom - 1; // no need for %np, because pfrom > 0 facedims[ind + 3] = facedims[ind]; rdims[ind + 3] = ldims[ind]; rdims[ind] = rdims[ind + 3] - dind - ( pto < extra ? 1 : 0 ); } else if( 1 == dijk[ind] && pfrom < np - 1 ) { // actual right neighbor pto = pfrom + 1; facedims[ind] = facedims[ind + 3]; rdims[ind] = ldims[ind + 3]; rdims[ind + 3] = rdims[ind] + dind + ( pto < extra ? 1 : 0 ); if( is_periodic && pfrom == np - 2 ) rdims[ind + 3]++; // neighbor is on periodic bdy } else if( -1 == dijk[ind] && !pfrom && gperiodic[ind] ) { // downward across periodic bdy pto = np - 1; facedims[ind + 3] = facedims[ind] = gdims[ind]; // by convention, facedims is within gdims, so lower value rdims[ind + 3] = gdims[ind + 3] + 1; // by convention, local dims one greater than gdims to indicate global lower value rdims[ind] = rdims[ind + 3] - dind - 1; across_bdy[ind] = -1; } else if( 1 == dijk[ind] && pfrom == np - 1 && is_periodic ) { // right across periodic bdy pto = 0; facedims[ind + 3] = facedims[ind] = gdims[ind]; // by convention, facedims is within gdims, so lowest value rdims[ind] = gdims[ind]; rdims[ind + 3] = rdims[ind] + dind + ( pto < extra ? 1 : 0 ); across_bdy[ind] = 1; } assert( -1 == pto || ( rdims[0] >= gdims[0] && ( rdims[3] <= gdims[3] || ( across_bdy[0] && !pfrom ) ) ) ); assert( -1 == pto || ( rdims[1] >= gdims[1] && ( rdims[4] <= gdims[4] || ( across_bdy[1] && !pfrom ) ) ) ); assert( -1 == pto || ( rdims[2] >= gdims[2] && rdims[5] <= gdims[5] ) ); assert( -1 == pto || ( facedims[0] >= rdims[0] && facedims[3] <= rdims[3] ) ); assert( -1 == pto || ( facedims[1] >= rdims[1] && facedims[4] <= rdims[4] ) ); assert( -1 == pto || ( facedims[2] >= rdims[2] && facedims[5] <= rdims[5] ) ); assert( -1 == pto || ( facedims[0] >= ldims[0] && facedims[3] <= ldims[3] ) ); assert( -1 == pto || ( facedims[1] >= ldims[1] && facedims[4] <= ldims[4] ) ); assert( -1 == pto || ( facedims[2] >= ldims[2] && facedims[5] <= ldims[5] ) ); return rval; }
ErrorCode moab::ScdInterface::get_neighbor_sqij | ( | int | np, |
int | pfrom, | ||
const int *const | gdims, | ||
const int *const | gperiodic, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [static, private] |
Definition at line 977 of file ScdInterface.cpp.
References compute_partition_sqij(), ErrorCode, MB_SUCCESS, and np.
Referenced by get_neighbor().
{ if( dijk[2] != 0 ) { // for sqij, there is no k neighbor, ever pto = -1; return MB_SUCCESS; } pto = -1; across_bdy[0] = across_bdy[1] = across_bdy[2] = 0; int lperiodic[3], pijk[3], ldims[6]; ErrorCode rval = compute_partition_sqij( np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk ); if( MB_SUCCESS != rval ) return rval; assert( pijk[0] * pijk[1] == np ); pto = -1; bool top_i = 0, top_j = 0, bot_i = 0, bot_j = 0; int ni = pfrom % pijk[0], nj = pfrom / pijk[0]; // row / column number of me if( ni == pijk[0] - 1 ) top_i = 1; if( nj == pijk[1] - 1 ) top_j = 1; if( !ni ) bot_i = 1; if( !nj ) bot_j = 1; if( ( !gperiodic[0] && bot_i && -1 == dijk[0] ) || // left and not periodic ( !gperiodic[0] && top_i && 1 == dijk[0] ) || // right and not periodic ( !gperiodic[1] && bot_j && -1 == dijk[1] ) || // bottom and not periodic ( !gperiodic[1] && top_j && 1 == dijk[1] ) ) // top and not periodic return MB_SUCCESS; std::copy( ldims, ldims + 6, facedims ); std::copy( ldims, ldims + 6, rdims ); pto = pfrom; int j = gdims[4] - gdims[1], dj = j / pijk[1], jextra = ( gdims[4] - gdims[1] ) % dj, i = gdims[3] - gdims[0], di = i / pijk[0], iextra = ( gdims[3] - gdims[0] ) % di; if( 0 != dijk[0] ) { pto = ( ni + dijk[0] + pijk[0] ) % pijk[0]; // get pto's ni value pto = nj * pijk[0] + pto; // then convert to pto assert( pto >= 0 && pto < np ); if( -1 == dijk[0] ) { facedims[3] = facedims[0]; if( bot_i ) { // going across lower periodic bdy in i across_bdy[0] = -1; rdims[3] = gdims[3] + 1; // +1 because ldims[3] on remote proc is gdims[3]+1 rdims[0] = rdims[3] - di - 1; // -1 to account for rdims[3] being one larger } else { rdims[3] = ldims[0]; rdims[0] = rdims[3] - di; } if( pto % pijk[0] < iextra ) rdims[0]--; } else { if( top_i ) { // going across lower periodic bdy in i facedims[3] = gdims[0]; across_bdy[0] = 1; } facedims[0] = facedims[3]; rdims[0] = ( top_i ? gdims[0] : ldims[3] ); rdims[3] = rdims[0] + di; if( pto % pijk[0] < iextra ) rdims[3]++; if( gperiodic[0] && ni == pijk[0] - 2 ) rdims[3]++; // remote proc is top_i and periodic } } if( 0 != dijk[1] ) { pto = ( pto + dijk[1] * pijk[0] + np ) % np; assert( pto >= 0 && pto < np ); if( -1 == dijk[1] ) { facedims[4] = facedims[1]; if( bot_j ) { // going across lower periodic bdy in j rdims[4] = gdims[4] + 1; // +1 because ldims[4] on remote proc is gdims[4]+1 rdims[1] = rdims[4] - dj - 1; // -1 to account for gdims[4] being one larger across_bdy[1] = -1; } else { rdims[4] = ldims[1]; rdims[1] = rdims[4] - dj; } if( pto / pijk[0] < jextra ) rdims[1]--; } else { if( top_j ) { // going across lower periodic bdy in j facedims[4] = gdims[1]; rdims[1] = gdims[1]; across_bdy[1] = 1; } else { rdims[1] = ldims[4]; } facedims[1] = facedims[4]; rdims[4] = rdims[1] + dj; if( nj + 1 < jextra ) rdims[4]++; if( gperiodic[1] && nj == pijk[1] - 2 ) rdims[4]++; // remote proc is top_j and periodic } } // rdims within gdims assert( -1 == pto || ( rdims[0] >= gdims[0] && ( rdims[3] <= gdims[3] + ( gperiodic[0] && pto % pijk[0] == pijk[0] - 1 ? 1 : 0 ) ) ) ); assert( -1 == pto || ( rdims[1] >= gdims[1] && ( rdims[4] <= gdims[4] + ( gperiodic[1] && pto / pijk[0] == pijk[1] - 1 ? 1 : 0 ) ) ) ); assert( -1 == pto || ( rdims[2] >= gdims[2] && rdims[5] <= gdims[5] ) ); // facedims within rdims assert( -1 == pto || ( ( facedims[0] >= rdims[0] || ( gperiodic[0] && pto % pijk[0] == pijk[0] - 1 && facedims[0] == gdims[0] ) ) ) ); assert( -1 == pto || ( facedims[3] <= rdims[3] ) ); assert( -1 == pto || ( ( facedims[1] >= rdims[1] || ( gperiodic[1] && pto / pijk[0] == pijk[1] - 1 && facedims[1] == gdims[1] ) ) ) ); assert( -1 == pto || ( facedims[4] <= rdims[4] ) ); assert( -1 == pto || ( facedims[2] >= rdims[2] && facedims[5] <= rdims[5] ) ); // facedims within ldims assert( -1 == pto || ( ( facedims[0] >= ldims[0] || ( top_i && facedims[0] == gdims[0] ) ) ) ); assert( -1 == pto || ( facedims[3] <= ldims[3] ) ); assert( -1 == pto || ( ( facedims[1] >= ldims[1] || ( gperiodic[1] && top_j && facedims[1] == gdims[1] ) ) ) ); assert( -1 == pto || ( facedims[4] <= ldims[4] ) ); assert( -1 == pto || ( facedims[2] >= ldims[2] && facedims[5] <= ldims[5] ) ); return MB_SUCCESS; }
ErrorCode moab::ScdInterface::get_neighbor_sqijk | ( | int | np, |
int | pfrom, | ||
const int *const | gdims, | ||
const int *const | gperiodic, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [static, private] |
Definition at line 1240 of file ScdInterface.cpp.
References compute_partition_sqijk(), ErrorCode, and MB_SUCCESS.
Referenced by get_neighbor().
{ if( gperiodic[0] || gperiodic[1] || gperiodic[2] ) return MB_FAILURE; pto = -1; across_bdy[0] = across_bdy[1] = across_bdy[2] = 0; int pijk[3], lperiodic[3], ldims[6]; ErrorCode rval = compute_partition_sqijk( np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk ); if( MB_SUCCESS != rval ) return rval; assert( pijk[0] * pijk[1] * pijk[2] == np ); pto = -1; bool top[3] = { false, false, false }, bot[3] = { false, false, false }; // nijk: rank in i/j/k direction int nijk[3] = { pfrom % pijk[0], ( pfrom % ( pijk[0] * pijk[1] ) ) / pijk[0], pfrom / ( pijk[0] * pijk[1] ) }; for( int i = 0; i < 3; i++ ) { if( nijk[i] == pijk[i] - 1 ) top[i] = true; if( !nijk[i] ) bot[i] = true; if( ( !gperiodic[i] && bot[i] && -1 == dijk[i] ) || // downward && not periodic ( !gperiodic[i] && top[i] && 1 == dijk[i] ) ) // upward && not periodic return MB_SUCCESS; } std::copy( ldims, ldims + 6, facedims ); std::copy( ldims, ldims + 6, rdims ); pto = pfrom; int delijk[3], extra[3]; // nijk_to: rank of pto in i/j/k direction int nijk_to[3]; for( int i = 0; i < 3; i++ ) { delijk[i] = ( gdims[i + 3] == gdims[i] ? 0 : ( gdims[i + 3] - gdims[i] ) / pijk[i] ); extra[i] = ( gdims[i + 3] - gdims[i] ) % delijk[i]; nijk_to[i] = ( nijk[i] + dijk[i] + pijk[i] ) % pijk[i]; } pto = nijk_to[2] * pijk[0] * pijk[1] + nijk_to[1] * pijk[0] + nijk_to[0]; assert( pto >= 0 && pto < np ); for( int i = 0; i < 3; i++ ) { if( 0 != dijk[i] ) { if( -1 == dijk[i] ) { facedims[i + 3] = facedims[i]; if( bot[i] ) { // going across lower periodic bdy in i rdims[i + 3] = gdims[i + 3] + 1; // +1 because ldims[4] on remote proc is gdims[4]+1 across_bdy[i] = -1; } else { rdims[i + 3] = ldims[i]; } rdims[i] = rdims[i + 3] - delijk[i]; if( nijk[i] < extra[i] ) rdims[i]--; } else { if( top[i] ) { // going across upper periodic bdy in i rdims[i] = gdims[i]; facedims[i + 3] = gdims[i]; across_bdy[i] = 1; } else { rdims[i] = ldims[i + 3]; } facedims[i] = facedims[i + 3]; rdims[i + 3] = rdims[i] + delijk[i]; if( nijk[i] < extra[i] ) rdims[i + 3]++; if( gperiodic[i] && nijk[i] == dijk[i] - 2 ) rdims[i + 3]++; // +1 because next proc is on periodic bdy } } } assert( -1 != pto ); #ifndef NDEBUG for( int i = 0; i < 3; i++ ) { assert( ( rdims[i] >= gdims[i] && ( rdims[i + 3] <= gdims[i + 3] || ( across_bdy[i] && bot[i] ) ) ) ); assert( ( ( facedims[i] >= rdims[i] || ( gperiodic[i] && rdims[i + 3] == gdims[i + 3] && facedims[i] == gdims[i] ) ) ) ); assert( ( facedims[i] >= ldims[i] && facedims[i + 3] <= ldims[i + 3] ) ); } #endif return MB_SUCCESS; }
ErrorCode moab::ScdInterface::get_neighbor_sqjk | ( | int | np, |
int | pfrom, | ||
const int *const | gdims, | ||
const int *const | gperiodic, | ||
const int *const | dijk, | ||
int & | pto, | ||
int * | rdims, | ||
int * | facedims, | ||
int * | across_bdy | ||
) | [static, private] |
Definition at line 1122 of file ScdInterface.cpp.
References compute_partition_sqjk(), ErrorCode, MB_SUCCESS, and np.
Referenced by get_neighbor().
{ if( dijk[0] != 0 ) { pto = -1; return MB_SUCCESS; } pto = -1; across_bdy[0] = across_bdy[1] = across_bdy[2] = 0; int pijk[3], lperiodic[3], ldims[6]; ErrorCode rval = compute_partition_sqjk( np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk ); if( MB_SUCCESS != rval ) return rval; assert( pijk[1] * pijk[2] == np ); pto = -1; bool top_j = 0, top_k = 0, bot_j = 0, bot_k = 0; int nj = pfrom % pijk[1], nk = pfrom / pijk[1]; if( nj == pijk[1] - 1 ) top_j = 1; if( nk == pijk[2] - 1 ) top_k = 1; if( !nj ) bot_j = 1; if( !nk ) bot_k = 1; if( ( !gperiodic[1] && bot_j && -1 == dijk[1] ) || // down and not periodic ( !gperiodic[1] && top_j && 1 == dijk[1] ) || // up and not periodic ( bot_k && -1 == dijk[2] ) || // k- bdy ( top_k && 1 == dijk[2] ) ) // k+ bdy return MB_SUCCESS; std::copy( ldims, ldims + 6, facedims ); std::copy( ldims, ldims + 6, rdims ); pto = pfrom; int dj = ( gdims[4] - gdims[1] ) / pijk[1], jextra = ( gdims[4] - gdims[1] ) % dj, dk = ( gdims[5] == gdims[2] ? 0 : ( gdims[5] - gdims[2] ) / pijk[2] ), kextra = ( gdims[5] - gdims[2] ) - dk * pijk[2]; assert( ( dj * pijk[1] + jextra == ( gdims[4] - gdims[1] ) ) && ( dk * pijk[2] + kextra == ( gdims[5] - gdims[2] ) ) ); if( 0 != dijk[1] ) { pto = ( nj + dijk[1] + pijk[1] ) % pijk[1]; // get pto's ni value pto = nk * pijk[1] + pto; // then convert to pto assert( pto >= 0 && pto < np ); if( -1 == dijk[1] ) { facedims[4] = facedims[1]; if( bot_j ) { // going across lower periodic bdy in j rdims[4] = gdims[4] + 1; // +1 because ldims[4] on remote proc is gdims[4]+1 across_bdy[1] = -1; } else { rdims[4] = ldims[1]; } rdims[1] = rdims[4] - dj; if( nj < jextra ) rdims[1]--; } else { if( top_j ) { // going across upper periodic bdy in j rdims[1] = gdims[1]; facedims[4] = gdims[1]; across_bdy[1] = 1; } else { rdims[1] = ldims[4]; } facedims[1] = facedims[4]; rdims[4] = rdims[1] + dj; if( nj < jextra ) rdims[4]++; if( gperiodic[1] && nj == dijk[1] - 2 ) rdims[4]++; // +1 because next proc is on periodic bdy } } if( 0 != dijk[2] ) { pto = ( pto + dijk[2] * pijk[1] + np ) % np; assert( pto >= 0 && pto < np ); if( -1 == dijk[2] ) { facedims[5] = facedims[2]; rdims[5] = ldims[2]; rdims[2] -= dk; if( pto / pijk[1] < kextra ) rdims[2]--; } else { facedims[2] = facedims[5]; rdims[2] = ldims[5]; rdims[5] += dk; if( pto / pijk[1] < kextra ) rdims[5]++; } } assert( -1 == pto || ( rdims[0] >= gdims[0] && rdims[3] <= gdims[3] ) ); assert( -1 == pto || ( rdims[1] >= gdims[1] && ( rdims[4] <= gdims[4] || ( across_bdy[1] && bot_j ) ) ) ); assert( -1 == pto || ( rdims[2] >= gdims[2] && rdims[5] <= gdims[5] ) ); assert( -1 == pto || ( facedims[0] >= rdims[0] && facedims[3] <= rdims[3] ) ); assert( -1 == pto || ( ( facedims[1] >= rdims[1] || ( gperiodic[1] && rdims[4] == gdims[4] && facedims[1] == gdims[1] ) ) ) ); assert( -1 == pto || ( facedims[4] <= rdims[4] ) ); assert( -1 == pto || ( facedims[2] >= rdims[2] && facedims[5] <= rdims[5] ) ); assert( -1 == pto || ( facedims[0] >= ldims[0] && facedims[3] <= ldims[3] ) ); assert( -1 == pto || ( facedims[1] >= ldims[1] && facedims[4] <= ldims[4] ) ); assert( -1 == pto || ( facedims[2] >= ldims[2] && facedims[5] <= ldims[5] ) ); return MB_SUCCESS; }
Return the ScdBox corresponding to the entity set passed in.
If the entity isn't a structured box set, NULL is returned.
eh | Entity whose box is being queried |
Definition at line 103 of file ScdInterface.cpp.
References box_set_tag(), mbImpl, and moab::Interface::tag_get_data().
Referenced by find_boxes(), and tag_shared_vertices().
{ ScdBox* scd_box = NULL; if( !box_set_tag( false ) ) return scd_box; mbImpl->tag_get_data( box_set_tag(), &eh, 1, &scd_box ); return scd_box; }
ErrorCode moab::ScdInterface::get_shared_vertices | ( | ParallelComm * | pcomm, |
ScdBox * | box, | ||
std::vector< int > & | procs, | ||
std::vector< int > & | offsets, | ||
std::vector< int > & | shared_indices | ||
) | [static, private] |
Get vertices shared with other processors.
get shared vertices for alljorkori partition scheme
Shared vertices returned as indices into each proc's handle space
box | Box used to get parametric space info |
procs | Procs this proc shares vertices with |
offsets | Offsets into indices list for each proc |
shared_indices | local/remote indices of shared vertices |
Definition at line 1442 of file ScdInterface.cpp.
References moab::ScdBox::box_dims(), ErrorCode, get_indices(), get_neighbor(), MB_SUCCESS, moab::ScdBox::par_data(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), and moab::ProcConfig::proc_size().
Referenced by tag_shared_vertices().
{ return MB_FAILURE; #else ErrorCode ScdInterface::get_shared_vertices( ParallelComm* pcomm, ScdBox* box, std::vector< int >& procs, std::vector< int >& offsets, std::vector< int >& shared_indices ) { // get index of partitioned dimension const int* ldims = box->box_dims(); ErrorCode rval; int ijkrem[6], ijkface[6], across_bdy[3]; for( int k = -1; k <= 1; k++ ) { for( int j = -1; j <= 1; j++ ) { for( int i = -1; i <= 1; i++ ) { if( !i && !j && !k ) continue; int pto; int dijk[] = { i, j, k }; rval = get_neighbor( pcomm->proc_config().proc_size(), pcomm->proc_config().proc_rank(), box->par_data(), dijk, pto, ijkrem, ijkface, across_bdy ); if( MB_SUCCESS != rval ) return rval; if( -1 != pto ) { if( procs.empty() || pto != *procs.rbegin() ) { procs.push_back( pto ); offsets.push_back( shared_indices.size() ); } rval = get_indices( ldims, ijkrem, across_bdy, ijkface, shared_indices ); if( MB_SUCCESS != rval ) return rval; // check indices against known #verts on local and remote // begin of this block is shared_indices[*offsets.rbegin()], end is // shared_indices.end(), halfway is // (shared_indices.size()-*offsets.rbegin())/2 #ifndef NDEBUG int start_idx = *offsets.rbegin(), end_idx = shared_indices.size(), mid_idx = ( start_idx + end_idx ) / 2; int num_local_verts = ( ldims[3] - ldims[0] + 1 ) * ( ldims[4] - ldims[1] + 1 ) * ( -1 == ldims[2] && -1 == ldims[5] ? 1 : ( ldims[5] - ldims[2] + 1 ) ), num_remote_verts = ( ijkrem[3] - ijkrem[0] + 1 ) * ( ijkrem[4] - ijkrem[1] + 1 ) * ( -1 == ijkrem[2] && -1 == ijkrem[5] ? 1 : ( ijkrem[5] - ijkrem[2] + 1 ) ); assert( *std::min_element( &shared_indices[start_idx], &shared_indices[mid_idx] ) >= 0 && *std::max_element( &shared_indices[start_idx], &shared_indices[mid_idx] ) < num_local_verts && *std::min_element( &shared_indices[mid_idx], &shared_indices[end_idx] ) >= 0 && *std::max_element( &shared_indices[mid_idx], &shared_indices[end_idx] ) < num_remote_verts ); #endif } } } } offsets.push_back( shared_indices.size() ); return MB_SUCCESS; #endif }
Tag moab::ScdInterface::global_box_dims_tag | ( | bool | create_if_missing = true | ) |
Return the tag marking the global lower and upper corners of boxes.
create_if_missing | If the tag does not yet exist, create it |
Definition at line 397 of file ScdInterface.cpp.
References ErrorCode, globalBoxDimsTag, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TYPE_INTEGER, mbImpl, moab::Interface::tag_get_handle(), and moab::Interface::tag_get_name().
{ // Reset globalBoxDimsTag in case it has been deleted (e.g. by Core::clean_up_failed_read) if( globalBoxDimsTag ) { std::string tag_name; if( MB_TAG_NOT_FOUND == mbImpl->tag_get_name( globalBoxDimsTag, tag_name ) ) globalBoxDimsTag = NULL; } if( globalBoxDimsTag || !create_if_missing ) return globalBoxDimsTag; ErrorCode rval = mbImpl->tag_get_handle( "GLOBAL_BOX_DIMS", 6, MB_TYPE_INTEGER, globalBoxDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != rval ) return 0; return globalBoxDimsTag; }
int moab::ScdInterface::gtol | ( | const int * | gijk, |
int | i, | ||
int | j, | ||
int | k | ||
) | [inline, static, private] |
Definition at line 1365 of file ScdInterface.hpp.
Referenced by get_indices().
{
return ( ( k - gijk[2] ) * ( gijk[3] - gijk[0] + 1 ) * ( gijk[4] - gijk[1] + 1 ) +
( j - gijk[1] ) * ( gijk[3] - gijk[0] + 1 ) + i - gijk[0] );
}
Interface * moab::ScdInterface::impl | ( | ) | const |
Return the MOAB Interface instance *.
Definition at line 52 of file ScdInterface.cpp.
References mbImpl.
Referenced by access_adjacencies(), eseq_test1b(), moab::ScdBox::get_adj_edge_or_face(), and moab::ScdBox::get_params().
{ return mbImpl; }
Tag moab::ScdInterface::part_method_tag | ( | bool | create_if_missing = true | ) |
Return the tag marking the partitioning method used to partition the box in parallel.
create_if_missing | If the tag does not yet exist, create it |
Definition at line 414 of file ScdInterface.cpp.
References ErrorCode, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_NOT_FOUND, MB_TAG_SPARSE, MB_TYPE_INTEGER, mbImpl, partMethodTag, moab::Interface::tag_get_handle(), and moab::Interface::tag_get_name().
Referenced by moab::NCHelper::create_conventional_tags().
{ // Reset partMethodTag in case it has been deleted (e.g. by Core::clean_up_failed_read) if( partMethodTag ) { std::string tag_name; if( MB_TAG_NOT_FOUND == mbImpl->tag_get_name( partMethodTag, tag_name ) ) partMethodTag = NULL; } if( partMethodTag || !create_if_missing ) return partMethodTag; ErrorCode rval = mbImpl->tag_get_handle( "PARTITION_METHOD", 1, MB_TYPE_INTEGER, partMethodTag, MB_TAG_SPARSE | MB_TAG_CREAT ); if( MB_SUCCESS != rval ) return 0; return partMethodTag; }
ErrorCode moab::ScdInterface::remove_box | ( | ScdBox * | box | ) | [protected] |
Remove the box from the list on ScdInterface.
Definition at line 449 of file ScdInterface.cpp.
References box(), MB_SUCCESS, and scdBoxes.
Referenced by moab::ScdBox::~ScdBox().
ErrorCode moab::ScdInterface::tag_shared_vertices | ( | ParallelComm * | pcomm, |
EntityHandle | seth | ||
) | [inline] |
Tag vertices with sharing data for parallel representations.
Given the ParallelComm object to use, tag the vertices shared with other processors
Definition at line 1447 of file ScdInterface.hpp.
References moab::Range::begin(), box(), moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_type(), get_scd_box(), MB_SUCCESS, MBENTITYSET, and mbImpl.
Referenced by construct_box(), moab::ParallelComm::resolve_shared_ents(), and tag_shared_vertices().
{ ScdBox* box = get_scd_box( seth ); if( !box ) { // look for contained boxes Range tmp_range; ErrorCode rval = mbImpl->get_entities_by_type( seth, MBENTITYSET, tmp_range ); if( MB_SUCCESS != rval ) return rval; for( Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); ++rit ) { box = get_scd_box( *rit ); if( box ) break; } } if( !box ) return MB_FAILURE; return tag_shared_vertices( pcomm, box ); }
ErrorCode moab::ScdInterface::tag_shared_vertices | ( | ParallelComm * | pcomm, |
ScdBox * | box | ||
) |
Tag vertices with sharing data for parallel representations.
Given the ParallelComm object to use, tag the vertices shared with other processors
Definition at line 733 of file ScdInterface.cpp.
References box(), moab::ScdBox::box_dimension(), moab::ScdBox::box_set(), moab::ParallelComm::check_all_shared_handles(), moab::ParallelComm::create_interface_sets(), moab::dum, moab::TupleList::enableWriteAccess(), ErrorCode, gdims, moab::ScdParData::gDims, moab::ParallelComm::get_buffers(), moab::ParallelComm::get_debug_verbosity(), moab::Interface::get_entities_by_dimension(), get_shared_vertices(), moab::TupleList::inc_n(), moab::TupleList::initialize(), moab::Range::insert(), moab::ParallelComm::list_entities(), MB_SET_ERR, MB_SUCCESS, mbImpl, moab::ScdBox::num_elements(), moab::ScdBox::par_data(), moab::ParallelComm::partition_sets(), moab::ScdParData::partMethod, moab::ProcConfig::proc_comm(), moab::ParallelComm::proc_config(), moab::TupleList::buffer::reset(), moab::Range::size(), moab::TupleList::sort(), moab::ScdBox::start_element(), moab::ScdBox::start_vertex(), tag_shared_vertices(), moab::ParallelComm::tag_shared_verts(), moab::TupleList::vi_wr, and moab::TupleList::vul_wr.
{ return MB_FAILURE; #else ErrorCode ScdInterface::tag_shared_vertices( ParallelComm* pcomm, ScdBox* box ) { EntityHandle seth = box->box_set(); // check the # ents in the box against the num in the set, to make sure it's only 1 box; // reuse tmp_range Range tmp_range; ErrorCode rval = mbImpl->get_entities_by_dimension( seth, box->box_dimension(), tmp_range ); if( MB_SUCCESS != rval ) return rval; if( box->num_elements() != (int)tmp_range.size() ) return MB_FAILURE; const int* gdims = box->par_data().gDims; if( ( gdims[0] == gdims[3] && gdims[1] == gdims[4] && gdims[2] == gdims[5] ) || -1 == box->par_data().partMethod ) return MB_FAILURE; // ok, we have a partitioned box; get the vertices shared with other processors std::vector< int > procs, offsets, shared_indices; rval = get_shared_vertices( pcomm, box, procs, offsets, shared_indices ); if( MB_SUCCESS != rval ) return rval; // post receives for start handles once we know how many to look for std::vector< MPI_Request > recv_reqs( procs.size(), MPI_REQUEST_NULL ), send_reqs( procs.size(), MPI_REQUEST_NULL ); std::vector< EntityHandle > rhandles( 4 * procs.size() ), shandles( 4 ); for( unsigned int i = 0; i < procs.size(); i++ ) { int success = MPI_Irecv( (void*)&rhandles[4 * i], 4 * sizeof( EntityHandle ), MPI_UNSIGNED_CHAR, procs[i], 1, pcomm->proc_config().proc_comm(), &recv_reqs[i] ); if( success != MPI_SUCCESS ) return MB_FAILURE; } // send our own start handles shandles[0] = box->start_vertex(); shandles[1] = 0; if( box->box_dimension() == 1 ) { shandles[1] = box->start_element(); shandles[2] = 0; shandles[3] = 0; } else if( box->box_dimension() == 2 ) { shandles[2] = box->start_element(); shandles[3] = 0; } else { shandles[2] = 0; shandles[3] = box->start_element(); } for( unsigned int i = 0; i < procs.size(); i++ ) { int success = MPI_Isend( (void*)&shandles[0], 4 * sizeof( EntityHandle ), MPI_UNSIGNED_CHAR, procs[i], 1, pcomm->proc_config().proc_comm(), &send_reqs[i] ); if( success != MPI_SUCCESS ) return MB_FAILURE; } // receive start handles and save info to a tuple list int incoming = procs.size(); int p, j, k; MPI_Status status; TupleList shared_data; shared_data.initialize( 1, 0, 2, 0, shared_indices.size() / 2 ); shared_data.enableWriteAccess(); j = 0; k = 0; while( incoming ) { int success = MPI_Waitany( procs.size(), &recv_reqs[0], &p, &status ); if( MPI_SUCCESS != success ) return MB_FAILURE; unsigned int num_indices = ( offsets[p + 1] - offsets[p] ) / 2; int *lh = &shared_indices[offsets[p]], *rh = lh + num_indices; for( unsigned int i = 0; i < num_indices; i++ ) { shared_data.vi_wr[j++] = procs[p]; shared_data.vul_wr[k++] = shandles[0] + lh[i]; shared_data.vul_wr[k++] = rhandles[4 * p] + rh[i]; shared_data.inc_n(); } incoming--; } // still need to wait for the send requests std::vector< MPI_Status > mult_status( procs.size() ); int success = MPI_Waitall( procs.size(), &send_reqs[0], &mult_status[0] ); if( MPI_SUCCESS != success ) { MB_SET_ERR( MB_FAILURE, "Failed in waitall in ScdInterface::tag_shared_vertices" ); } // sort by local handle TupleList::buffer sort_buffer; sort_buffer.buffer_init( shared_indices.size() / 2 ); shared_data.sort( 1, &sort_buffer ); sort_buffer.reset(); // process into sharing data std::map< std::vector< int >, std::vector< EntityHandle > > proc_nvecs; Range dum; rval = pcomm->tag_shared_verts( shared_data, proc_nvecs, dum, 0 ); if( MB_SUCCESS != rval ) return rval; // create interface sets rval = pcomm->create_interface_sets( proc_nvecs ); if( MB_SUCCESS != rval ) return rval; // add the box to the PComm's partitionSets pcomm->partition_sets().insert( box->box_set() ); // make sure buffers are allocated for communicating procs for( std::vector< int >::iterator pit = procs.begin(); pit != procs.end(); ++pit ) pcomm->get_buffers( *pit ); if( pcomm->get_debug_verbosity() > 1 ) pcomm->list_entities( NULL, 1 ); #ifndef NDEBUG rval = pcomm->check_all_shared_handles(); if( MB_SUCCESS != rval ) return rval; #endif return MB_SUCCESS; #endif }
friend class ScdBox [friend] |
Definition at line 154 of file ScdInterface.hpp.
Referenced by create_scd_sequence().
Tag moab::ScdInterface::boxDimsTag [private] |
tag representing box lower and upper corners
Definition at line 494 of file ScdInterface.hpp.
Referenced by box_dims_tag(), find_boxes(), and moab::ScdBox::ScdBox().
Tag moab::ScdInterface::boxPeriodicTag [private] |
tag representing whether box is periodic in i and j
Definition at line 491 of file ScdInterface.hpp.
Referenced by box_periodic_tag(), and moab::ScdBox::ScdBox().
Tag moab::ScdInterface::boxSetTag [private] |
tag pointing from set to ScdBox
Definition at line 503 of file ScdInterface.hpp.
Referenced by box_set_tag(), and find_boxes().
Tag moab::ScdInterface::globalBoxDimsTag [private] |
tag representing global lower and upper corners
Definition at line 497 of file ScdInterface.hpp.
Referenced by global_box_dims_tag().
Interface* moab::ScdInterface::mbImpl [private] |
interface instance
Definition at line 482 of file ScdInterface.hpp.
Referenced by assign_global_ids(), moab::ScdBox::box_dimension(), box_dims_tag(), box_periodic_tag(), box_set_tag(), construct_box(), create_box_set(), create_scd_sequence(), find_boxes(), get_scd_box(), global_box_dims_tag(), impl(), part_method_tag(), moab::ScdBox::ScdBox(), tag_shared_vertices(), moab::ScdBox::~ScdBox(), and ~ScdInterface().
Tag moab::ScdInterface::partMethodTag [private] |
tag representing partition method
Definition at line 500 of file ScdInterface.hpp.
Referenced by part_method_tag().
std::vector< ScdBox* > moab::ScdInterface::scdBoxes [private] |
structured mesh blocks; stored as ScdBox objects, can get sets from those
Definition at line 488 of file ScdInterface.hpp.
Referenced by add_box(), find_boxes(), get_boxes(), remove_box(), ScdInterface(), and ~ScdInterface().
bool moab::ScdInterface::searchedBoxes [private] |
whether we've searched the database for boxes yet
Definition at line 485 of file ScdInterface.hpp.
Referenced by find_boxes().