LCOV - code coverage report
Current view: top level - src/moab - ScdInterface.hpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 267 395 67.6 %
Date: 2020-12-16 07:07:30 Functions: 30 34 88.2 %
Branches: 298 676 44.1 %

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

Generated by: LCOV version 1.11