MOAB: Mesh Oriented datABase  (version 5.3.0)
moab::ScdInterface Class Reference

A structured mesh interface for MOAB-based data. More...

#include <moab/ScdInterface.hpp>

+ Collaboration diagram for moab::ScdInterface:

Public Member Functions

 ScdInterface (Interface *impl, bool find_boxes=false)
 Constructor.
 ~ScdInterface ()
Interfaceimpl () 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.
ScdBoxget_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

InterfacembImpl
 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

Detailed Description

A structured mesh interface for MOAB-based data.

Structured mesh in MOAB is created and accessed through the ScdInterface and ScdBox classes.

Construction and Representation

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.

Parametric Space

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.

Periodic Meshes

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.

Parallel Representation

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.

Adjacent Entities

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.

Evaluation

The ScdBox class provides functions for evaluating the mesh based on the ijk parameter space. These functions are inlined where possible, for efficiency.

Examples:
StructuredMeshSimple.cpp.

Definition at line 151 of file ScdInterface.hpp.


Constructor & Destructor Documentation

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.

Parameters:
implMOAB instance
find_boxesIf 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() );
}

Member Function Documentation

Add the box to the list on ScdInterface.

Definition at line 444 of file ScdInterface.cpp.

References MB_SUCCESS, and scdBoxes.

Referenced by moab::ScdBox::ScdBox().

{
    scdBoxes.push_back( box );
    return MB_SUCCESS;
}

assign global ids to vertices in this box

Definition at line 243 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.

Parameters:
create_if_missingIf the tag does not yet exist, create it

Definition at line 363 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.

Parameters:
create_if_missingIf the tag does not yet exist, create it

Definition at line 346 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.

Parameters:
create_if_missingIf the tag does not yet exist, create it

Definition at line 413 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.

Parameters:
npNumber of processors
nrRank of this processor
par_dataScdParData object that contains input global parameter space, desired partitioning method, and information about global periodicity.
ldimsLocal parameters for grid
lperiodicWhether or not a given dimension is locally periodic
pdimsNumber of procs in i, j, k directions

Definition at line 751 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 877 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 781 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 960 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 1135 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 1053 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.

Parameters:
lowLower corner in parameter space
highHigher corner in parameter space
coordsCoordinates of vertices, interleaved (xyzxyz...); if NULL, coords are set to parametric values
num_coordsNumber of coordinate values
new_boxReference to box of structured mesh
lperiodic[3]If lperiodic[s] != 0, direction s is locally periodic
par_dataIf non-NULL, this will get stored on the ScdBox once created, contains info about global parallel nature of ScdBox across procs
assign_global_idsIf true, assigns 1-based global ids to vertices using GLOBAL_ID_TAG_NAME
resolve_shared_entsIf != -1, resolves shared entities up to and including dimension equal to value
Examples:
StructuredMeshSimple.cpp.

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.

Parameters:
lowLower corner parameters for this box
highUpper corner parameters for this box
scd_setEntity 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 321 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.

Parameters:
lowLower corner of structured box
highHigher corner of structured box
typeEntityType, one of MBVERTEX, MBEDGE, MBQUAD, MBHEX
starting_idRequested start id of entities
new_boxReference 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 275 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.

Parameters:
boxesVector 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;
}

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.

Parameters:
boxesRange 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.

Parameters:
boxesStructured boxes

Definition at line 450 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 1241 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

Parameters:
np(in) Total # procs
nrProcessor 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 1277 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 827 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 1281 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 937 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 1186 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 1075 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.

Parameters:
ehEntity 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

Parameters:
boxBox used to get parametric space info
procsProcs this proc shares vertices with
offsetsOffsets into indices list for each proc
shared_indiceslocal/remote indices of shared vertices

Definition at line 1376 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.

Parameters:
create_if_missingIf the tag does not yet exist, create it

Definition at line 379 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 1235 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] );
}

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.

Parameters:
create_if_missingIf the tag does not yet exist, create it

Definition at line 396 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;
}

Remove the box from the list on ScdInterface.

Definition at line 431 of file ScdInterface.cpp.

References box(), MB_SUCCESS, and scdBoxes.

Referenced by moab::ScdBox::~ScdBox().

{
    std::vector< ScdBox* >::iterator vit = std::find( scdBoxes.begin(), scdBoxes.end(), box );
    if( vit != scdBoxes.end() )
    {
        scdBoxes.erase( vit );
        return MB_SUCCESS;
    }
    else
        return MB_FAILURE;
}

Tag vertices with sharing data for parallel representations.

Given the ParallelComm object to use, tag the vertices shared with other processors

Definition at line 1308 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 );
}

Tag vertices with sharing data for parallel representations.

Given the ParallelComm object to use, tag the vertices shared with other processors

Definition at line 702 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
}

Friends And Related Function Documentation

friend class ScdBox [friend]

Definition at line 154 of file ScdInterface.hpp.

Referenced by create_scd_sequence().


Member Data Documentation

tag representing box lower and upper corners

Definition at line 408 of file ScdInterface.hpp.

Referenced by box_dims_tag(), find_boxes(), and moab::ScdBox::ScdBox().

tag representing whether box is periodic in i and j

Definition at line 405 of file ScdInterface.hpp.

Referenced by box_periodic_tag(), and moab::ScdBox::ScdBox().

tag pointing from set to ScdBox

Definition at line 417 of file ScdInterface.hpp.

Referenced by box_set_tag(), and find_boxes().

tag representing global lower and upper corners

Definition at line 411 of file ScdInterface.hpp.

Referenced by global_box_dims_tag().

tag representing partition method

Definition at line 414 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 402 of file ScdInterface.hpp.

Referenced by add_box(), find_boxes(), get_boxes(), remove_box(), ScdInterface(), and ~ScdInterface().

whether we've searched the database for boxes yet

Definition at line 399 of file ScdInterface.hpp.

Referenced by find_boxes().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines