moab
moab::ScdInterface Class Reference

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

#include <moab/ScdInterface.hpp>

List of all members.

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 (HomCoord low, 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)
 Get information about the neighbor in the dijk[] direction, where dijk can be -1 or 1 for all 3 params.

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 *const gijk, 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 *const gijk, 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 *const gijk, 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 *const gijk, 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 *const gijk, 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 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.

directions, the parameter extent is that for vertices, with edge parameter extents one fewer.

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 136 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 27 of file ScdInterface.cpp.

Definition at line 40 of file ScdInterface.cpp.

{
  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 437 of file ScdInterface.cpp.

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

assign global ids to vertices in this box

Definition at line 238 of file ScdInterface.cpp.

{
  // Get a ptr to global id memory
  void* data;
  int count = 0;
  Tag gid_tag;
  ErrorCode rval = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, 
                                          MB_TAG_CREAT & MB_TAG_DENSE, &count);
  ERRORR(rval, "Trouble getting global id tag handle.");
  Range tmp_range(box->start_vertex(), box->start_vertex() + box->num_vertices());
  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 357 of file ScdInterface.cpp.

{
  // 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 340 of file ScdInterface.cpp.

{
  // 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 408 of file ScdInterface.cpp.

{
  // 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 743 of file ScdInterface.hpp.

{
  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 *const  gijk,
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 860 of file ScdInterface.hpp.

{
  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 *const  gijk,
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 777 of file ScdInterface.hpp.

{
    // 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 *const  gijk,
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 934 of file ScdInterface.hpp.

{
  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 = std::lower_bound(ppfactors.begin(), ppfactors.end(), ijratio) - 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 *const  gijk,
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 1085 of file ScdInterface.hpp.

{
  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 *const  gijk,
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 1014 of file ScdInterface.hpp.

{
  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 105 of file ScdInterface.cpp.

{
    // 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 USE_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);
    high.set(ldims+3);
    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 USE_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 318 of file ScdInterface.cpp.

{
    // 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 ( HomCoord  low,
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 269 of file ScdInterface.cpp.

{
  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);
  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 58 of file ScdInterface.cpp.

{
  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 73 of file ScdInterface.cpp.

{
  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) ) ;
    }
  }

  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 443 of file ScdInterface.cpp.

{
  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 1176 of file ScdInterface.hpp.

{
    // 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 1203 of file ScdInterface.hpp.

{
  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 796 of file ScdInterface.cpp.

{
  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 1197 of file ScdInterface.cpp.

{
  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 895 of file ScdInterface.cpp.

{
  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 1114 of file ScdInterface.cpp.

{
  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 1016 of file ScdInterface.cpp.

{
  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 96 of file ScdInterface.cpp.

{
  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 1284 of file ScdInterface.cpp.

{
  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 374 of file ScdInterface.cpp.

{
  // 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 1171 of file ScdInterface.hpp.

{
  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 53 of file ScdInterface.cpp.

{
  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 391 of file ScdInterface.cpp.

{
  // 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 426 of file ScdInterface.cpp.

{
  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 1236 of file ScdInterface.hpp.

{
  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 680 of file ScdInterface.cpp.

{
  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(&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(&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--;
  }

    // 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 139 of file ScdInterface.hpp.


Member Data Documentation

tag representing box lower and upper corners

Definition at line 400 of file ScdInterface.hpp.

tag representing whether box is periodic in i and j

Definition at line 397 of file ScdInterface.hpp.

tag pointing from set to ScdBox

Definition at line 409 of file ScdInterface.hpp.

tag representing global lower and upper corners

Definition at line 403 of file ScdInterface.hpp.

interface instance

Definition at line 388 of file ScdInterface.hpp.

tag representing partition method

Definition at line 406 of file ScdInterface.hpp.

std::vector<ScdBox*> moab::ScdInterface::scdBoxes [private]

structured mesh blocks; stored as ScdBox objects, can get sets from those

Definition at line 394 of file ScdInterface.hpp.

whether we've searched the database for boxes yet

Definition at line 391 of file ScdInterface.hpp.


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