[MOAB-dev] commit/MOAB: 10 new changesets

Vijay S. Mahadevan vijay.m at gmail.com
Wed Jan 8 21:17:38 CST 2014


All,

Sorry, I didn't mean to merge my fork's master to fathom:master in the
above commit. I bungled up something when cherry-picking. Hopefully,
nothing got broken because the additional stuff in the diff are due to
the rebase. Let me know if there are issues.

Vijay

On Wed, Jan 8, 2014 at 8:03 PM,  <commits-noreply at bitbucket.org> wrote:
> 10 new commits in MOAB:
>
> https://bitbucket.org/fathomteam/moab/commits/bd27ccd0b91d/
> Changeset:   bd27ccd0b91d
> Branch:      None
> User:        vijaysm
> Date:        2013-08-14 06:08:59
> Summary:     Merged fathomteam/moab into master
> Affected #:  34 files
>
> diff --git a/README b/README
> index 563265c..6bcf434 100644
> --- a/README
> +++ b/README
> @@ -82,3 +82,4 @@ Implementation:
>  2.00 (11/1/06): LOTS of bug fixes & improvements
>  1.00 (2/1/04): Initial release
>
> +
>
> diff --git a/configure.ac b/configure.ac
> index 24f425b..b08389a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1146,6 +1146,7 @@ AC_SUBST(CGM_CPPFLAGS)
>  AC_SUBST(CGM_LDFLAGS)
>  AC_SUBST(CGM_LTFLAGS)
>  AC_SUBST(CGM_LIBS)
> +AC_SUBST(CGM_DIR)
>
>  AM_CONDITIONAL( HAVE_CGM, [test "x$CGM_MISSING" = "xno"] )
>
>
> diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
> index ed23052..32d7fe1 100644
> --- a/doc/DG/moabDG.h
> +++ b/doc/DG/moabDG.h
> @@ -29,7 +29,7 @@
>    \section sequence  EntitySequence & SequenceData
>
>    \subsection figure1 Figure 1: EntitySequences For One SequenceData
> -   <img src="../DG/figure1.jpg">
> +  \image html figure1.jpg
>
>    \ref dg-figures "List of Figures"
>
> @@ -108,7 +108,7 @@ enforces the following four rules on its contained data:
>  .
>
>    \subsection figure2 Figure 2: SequenceManager and Related Classes
> -   <img src="../DG/figure2.jpg">
> +  \image html figure2.jpg
>
>    \ref dg-figures "List of Figures"
>
> @@ -187,7 +187,7 @@ than is required at a given time for contained objects.
>  - MeshSet
>
>    \subsection figure3 Figure 3: SequenceManager and Related Classes
> -    <img src="../DG/figure3.jpg">
> +  \image html figure3.jpg
>
>    \ref dg-figures "List of Figures"
>
>
> diff --git a/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
> index e02c112..8f81cff 100644
> --- a/doc/MetaData/metadata.h
> +++ b/doc/MetaData/metadata.h
> @@ -204,6 +204,10 @@ Read the time step number whose time value is equal to or greater than the speci
>  specified variable(s). Tag names for the variable(s) will be formed by appending the time step number
>  to the variable name. Multiple time step values can be specified, separated from each other by commas.
>
> +<H3>gather_set[=\<rank\>] </H3>
> +
> +Create a gather set (associated with tag GATHER_SET) on one processor with the specified rank, to duplicate entities on other processors. If the rank is not specified, it will be rank 0 by default. If an invalid rank is passed, no gather set will be created. Gather set is specially used by HOMME, MPAS, and any other unstructured grid.
> +
>  \ref md-contents "Top"
>
>    \section meta-references References
>
> diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
> index c5231fa..a6a6f4a 100644
> --- a/doc/UG/moabUG.h
> +++ b/doc/UG/moabUG.h
> @@ -18,7 +18,7 @@
>   - Timothy J. Tautges (Argonne National Lab, Univ Wisconsin-Madison)
>   - Iulian Grindeanu (Argonne National Lab)
>   - Rajeev Jain (Argonne National Lab)
> - - Xiabing Xu (Argonne National Lab)
> + - Danqing Wu  (Argonne National Lab)
>
>
>   <h2>Emeritus members:</h2>
> @@ -27,6 +27,7 @@
>   - Brandon M. Smith
>   - Hong-Jun Kim
>   - Jim Porter
> + - Xiabing Xu
>
>    \page contents Table of Contents
>
>
> diff --git a/doc/metadata_info.doc b/doc/metadata_info.doc
> index a19c0a2..6e3eb34 100644
> Binary files a/doc/metadata_info.doc and b/doc/metadata_info.doc differ
>
> diff --git a/doc/metadata_info.pdf b/doc/metadata_info.pdf
> index 710cc55..376aa51 100644
> Binary files a/doc/metadata_info.pdf and b/doc/metadata_info.pdf differ
>
> diff --git a/doc/user.dox.in b/doc/user.dox.in
> index adb22ef..4e1c773 100644
> --- a/doc/user.dox.in
> +++ b/doc/user.dox.in
> @@ -321,7 +321,7 @@ INPUT                  = @top_srcdir@/src @top_srcdir@/src/moab \
>  # and *.h) to filter out the source-files in the directories. If left
>  # blank all files are included.
>
> -FILE_PATTERNS          = *.cpp *.hpp *.h *.dox
> +FILE_PATTERNS          = *.cpp *.hpp *.h *.dox *.F90
>  #FILE_PATTERNS          = *.dox
>
>  # The RECURSIVE tag can be used to turn specify whether or not subdirectories
> @@ -359,7 +359,7 @@ EXAMPLE_PATTERNS       =
>  # directories that contain image that are included in the documentation (see
>  # the \image command).
>
> -IMAGE_PATH             =
> +IMAGE_PATH             =  @top_srcdir@/doc/DG/
>
>  # The INPUT_FILTER tag can be used to specify a program that doxygen should
>  # invoke to filter for each input file. Doxygen will invoke the filter program
>
> diff --git a/examples/DirectAccessNoHolesF90.F90 b/examples/DirectAccessNoHolesF90.F90
> index 3cf5fa7..c3cceeb 100644
> --- a/examples/DirectAccessNoHolesF90.F90
> +++ b/examples/DirectAccessNoHolesF90.F90
> @@ -1,42 +1,41 @@
> -! @example DirectAccessNoHolesF90.F90 \n
> -! \brief Use direct access to MOAB data to avoid calling through API, in Fortran90 \n
> -!
> -! This example creates a 1d row of quad elements, such that all quad and vertex handles
> -! are contiguous in the handle space and in the database.  Then it shows how to get access
> -! to pointers to MOAB-native data for vertex coordinates, quad connectivity, and tag storage
> -! (vertex to quad adjacency lists aren't accessible from Fortran because they are std::vector's).
> -! This allows applications to access this data directly
> -! without going through MOAB's API.  In cases where the mesh is not changing (or only mesh
> -! vertices are moving), this can save significant execution time in applications.
> -!
> -! Using direct access (or MOAB in general) from Fortran is complicated in two specific ways:
> -! 1) There is no way to use arrays with specified dimension starting/ending values with ISO_C_BINDING;
> -!    therefore, all arrays passed back from MOAB/iMesh must use 1-based indices; this makes it a bit
> -!    more difficult to traverse the direct arrays.  In this example, I explicitly use indices that
> -!    look like my_array(1+v_ind...) to remind users of this.
> -! 2) Arithmetic on handles is complicated by the fact that Fortran has no unsigned integer type.  I get
> -!    around this by assigning to a C-typed variable first, before the handle arithmetic.  This seems to
> -!    work fine.  C-typed variables are part of the Fortran95 standard.
> -!
> -!  ----------------------
> -!  |      |      |      |
> -!  |      |      |      | ...
> -!  |      |      |      |
> -!  ----------------------
> -!
> -!    -#  Initialize MOAB \n
> -!    -#  Create a quad mesh, as depicted above
> -!    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
> -!    -#  Get connectivity, coordinate, tag1 iterators
> -!    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
> -!    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
> -!    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
> -!
> -! <b>To compile</b>: \n
> -!    make DirectAccessNoHolesF90 MOAB_DIR=<installdir>  \n
> -! <b>To run</b>: ./DirectAccessNoHolesF90 [-nquads <# quads>]\n
> -!
> -!
> +!> @example DirectAccessNoHolesF90.F90
> +!! \brief Use direct access to MOAB data to avoid calling through API, in Fortran90 \n
> +!!
> +!! This example creates a 1d row of quad elements, such that all quad and vertex handles
> +!! are contiguous in the handle space and in the database.  Then it shows how to get access
> +!! to pointers to MOAB-native data for vertex coordinates, quad connectivity, and tag storage
> +!! (vertex to quad adjacency lists aren't accessible from Fortran because they are std::vector's).
> +!! This allows applications to access this data directly
> +!! without going through MOAB's API.  In cases where the mesh is not changing (or only mesh
> +!! vertices are moving), this can save significant execution time in applications.
> +!!
> +!! Using direct access (or MOAB in general) from Fortran is complicated in two specific ways:
> +!! 1) There is no way to use arrays with specified dimension starting/ending values with ISO_C_BINDING;
> +!!    therefore, all arrays passed back from MOAB/iMesh must use 1-based indices; this makes it a bit
> +!!    more difficult to traverse the direct arrays.  In this example, I explicitly use indices that
> +!!    look like my_array(1+v_ind...) to remind users of this.
> +!! 2) Arithmetic on handles is complicated by the fact that Fortran has no unsigned integer type.  I get
> +!!    around this by assigning to a C-typed variable first, before the handle arithmetic.  This seems to
> +!!    work fine.  C-typed variables are part of the Fortran95 standard.
> +!!
> +!!  ----------------------
> +!!  |      |      |      |
> +!!  |      |      |      | ...
> +!!  |      |      |      |
> +!!  ----------------------
> +!!
> +!!    -#  Initialize MOAB \n
> +!!    -#  Create a quad mesh, as depicted above
> +!!    -#  Create 2 dense tags (tag1, tag2) for avg position to assign to quads, and # verts per quad (tag3)
> +!!    -#  Get connectivity, coordinate, tag1 iterators
> +!!    -#  Iterate through quads, computing midpoint based on vertex positions, set on quad-based tag1
> +!!    -#  Iterate through vertices, summing positions into tag2 on connected quads and incrementing vertex count
> +!!    -#  Iterate through quads, normalizing tag2 by vertex count and comparing values of tag1 and tag2
> +!!
> +!! <b>To compile</b>: \n
> +!!    make DirectAccessNoHolesF90 MOAB_DIR=<installdir>  \n
> +!! <b>To run</b>: ./DirectAccessNoHolesF90 [-nquads <# quads>]\n
> +!!
>
>  #define CHECK(a) \
>    if (a .ne. iBase_SUCCESS) call exit(a)
>
> diff --git a/itaps/iBase.h b/itaps/iBase.h
> index 933b9d6..e61f92d 100644
> --- a/itaps/iBase.h
> +++ b/itaps/iBase.h
> @@ -269,8 +269,6 @@ enum iBase_TagValueType {
>   *
>   * \subpage imeshp
>   *
> - * \subpage igeom
> - *
>   * \subpage error
>   *
>   * \subpage trio
>
> diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
> index 8084640..1f021ff 100644
> --- a/src/ScdInterface.cpp
> +++ b/src/ScdInterface.cpp
> @@ -20,7 +20,9 @@
>
>  namespace moab
>  {
> -
> +
> +const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "trivial", "nopart"};
> +
>  ScdInterface::ScdInterface(Core *imp, bool boxes)
>          : mbImpl(imp),
>            searchedBoxes(false),
> @@ -248,7 +250,7 @@ Tag ScdInterface::box_periodic_tag(bool create_if_missing)
>  {
>    if (boxPeriodicTag || !create_if_missing) return boxPeriodicTag;
>
> -  ErrorCode rval = mbImpl->tag_get_handle("BOX_PERIODIC", 2, MB_TYPE_INTEGER,
> +  ErrorCode rval = mbImpl->tag_get_handle("BOX_PERIODIC", 3, MB_TYPE_INTEGER,
>                                            boxPeriodicTag, MB_TAG_SPARSE|MB_TAG_CREAT);
>    if (MB_SUCCESS != rval) return 0;
>    return boxPeriodicTag;
> @@ -323,7 +325,7 @@ ScdBox::ScdBox(ScdInterface *impl, EntityHandle bset,
>          : scImpl(impl), boxSet(bset), vertDat(NULL), elemSeq(NULL), startVertex(0), startElem(0)
>  {
>    for (int i = 0; i < 6; i++) boxDims[i] = 0;
> -  for (int i = 0; i < 2; i++) locallyPeriodic[i] = false;
> +  for (int i = 0; i < 3; i++) locallyPeriodic[i] = false;
>    VertexSequence *vseq = dynamic_cast<VertexSequence *>(seq1);
>    if (vseq) vertDat = dynamic_cast<ScdVertexData*>(vseq->data());
>    if (vertDat) {
> @@ -676,13 +678,6 @@ ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, EntityHandle se
>  #endif
>  }
>
> -#ifndef USE_MPI
> -ErrorCode ScdInterface::get_neighbor_alljkbal(int , int ,
> -                                              const int * const , const int * const , const int * const ,
> -                                              int &, int *, int *, int *)
> -{
> -  return MB_FAILURE;
> -#else
>  ErrorCode ScdInterface::get_neighbor_alljkbal(int np, int pfrom,
>                                                const int * const gdims, const int * const gperiodic, const int * const dijk,
>                                                int &pto, int *rdims, int *facedims, int *across_bdy)
> @@ -693,7 +688,7 @@ ErrorCode ScdInterface::get_neighbor_alljkbal(int np, int pfrom,
>    }
>
>    pto = -1;
> -  across_bdy[0] = across_bdy[1] = 0;
> +  across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
>
>    int ldims[6], pijk[3], lperiodic[2];
>    ErrorCode rval = compute_partition_alljkbal(np, pfrom, gdims, gperiodic,
> @@ -780,16 +775,8 @@ ErrorCode ScdInterface::get_neighbor_alljkbal(int np, int pfrom,
>    assert(-1 == pto || (facedims[5] <= ldims[5]));
>
>    return MB_SUCCESS;
> -#endif
>  }
>
> -#ifndef USE_MPI
> -ErrorCode ScdInterface::get_neighbor_sqij(int , int ,
> -                                          const int * const , const int * const , const int * const ,
> -                                          int &, int *, int *, int *)
> -{
> -  return MB_FAILURE;
> -#else
>  ErrorCode ScdInterface::get_neighbor_sqij(int np, int pfrom,
>                                            const int * const gdims, const int * const gperiodic, const int * const dijk,
>                                            int &pto, int *rdims, int *facedims, int *across_bdy)
> @@ -801,7 +788,7 @@ ErrorCode ScdInterface::get_neighbor_sqij(int np, int pfrom,
>    }
>
>    pto = -1;
> -  across_bdy[0] = across_bdy[1] = 0;
> +  across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
>    int lperiodic[3], pijk[3], ldims[6];
>    ErrorCode rval = compute_partition_sqij(np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk);
>    if (MB_SUCCESS != rval) return rval;
> @@ -909,16 +896,8 @@ ErrorCode ScdInterface::get_neighbor_sqij(int np, int pfrom,
>    assert (-1 == pto || (facedims[2] >= ldims[2] && facedims[5] <= ldims[5]));
>
>    return MB_SUCCESS;
> -#endif
>  }
>
> -#ifndef USE_MPI
> -ErrorCode ScdInterface::get_neighbor_sqjk(int , int ,
> -                                          const int * const , const int * const , const int * const ,
> -                                          int &, int *, int *, int *)
> -{
> -  return MB_FAILURE;
> -#else
>  ErrorCode ScdInterface::get_neighbor_sqjk(int np, int pfrom,
>                                            const int * const gdims, const int * const gperiodic, const int * const dijk,
>                                            int &pto, int *rdims, int *facedims, int *across_bdy)
> @@ -929,7 +908,7 @@ ErrorCode ScdInterface::get_neighbor_sqjk(int np, int pfrom,
>    }
>
>    pto = -1;
> -  across_bdy[0] = across_bdy[1] = 0;
> +  across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
>    int pijk[3], lperiodic[3], ldims[6];
>    ErrorCode rval = compute_partition_sqjk(np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk);
>    if (MB_SUCCESS != rval) return rval;
> @@ -952,7 +931,7 @@ ErrorCode ScdInterface::get_neighbor_sqjk(int np, int pfrom,
>    pto = pfrom;
>    int dj = (gdims[4] - gdims[1]) / pijk[1], jextra = (gdims[4] - gdims[1]) % dj,
>        dk = (gdims[5] == gdims[2] ? 0 : (gdims[5] - gdims[2]) / pijk[2]), kextra = (gdims[5] - gdims[2]) - dk*pijk[2];
> -
> +  assert((dj*pijk[1] + jextra == (gdims[4]-gdims[1])) && (dk*pijk[2] + kextra == (gdims[5]-gdims[2])));
>    if (0 != dijk[1]) {
>      pto = (nj + dijk[1] + pijk[1]) % pijk[1]; // get pto's ni value
>      pto = nk*pijk[1] + pto;  // then convert to pto
> @@ -993,7 +972,7 @@ ErrorCode ScdInterface::get_neighbor_sqjk(int np, int pfrom,
>        facedims[5] = facedims[2];
>        rdims[5] = ldims[2];
>        rdims[2] -= dk;
> -      if (nk < kextra) rdims[2]--;
> +      if (pto/pijk[1] < kextra) rdims[2]--;
>      }
>      else {
>        facedims[2] = facedims[5];
> @@ -1015,16 +994,91 @@ ErrorCode ScdInterface::get_neighbor_sqjk(int np, int pfrom,
>    assert(-1 == pto || (facedims[2] >= ldims[2] && facedims[5] <= ldims[5]));
>
>    return MB_SUCCESS;
> -#endif
>  }
>
> -#ifndef USE_MPI
> -ErrorCode ScdInterface::get_neighbor_alljorkori(int , int ,
> -                                                const int * const , const int * const , const int * const ,
> -                                                int &, int *, int *, int *)
> +ErrorCode ScdInterface::get_neighbor_sqijk(int np, int pfrom,
> +                                           const int * const gdims, const int * const gperiodic, const int * const dijk,
> +                                           int &pto, int *rdims, int *facedims, int *across_bdy)
>  {
> -  return MB_FAILURE;
> -#else
> +  if (gperiodic[0] || gperiodic[1] || gperiodic[2]) return MB_FAILURE;
> +
> +  pto = -1;
> +  across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
> +  int pijk[3], lperiodic[3], ldims[6];
> +  ErrorCode rval = compute_partition_sqijk(np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk);
> +  if (MB_SUCCESS != rval) return rval;
> +  assert(pijk[0] * pijk[1] * pijk[2] == np);
> +  pto = -1;
> +  bool top[3] = {false, false, false}, bot[3] = {false, false, false};
> +    // nijk: rank in i/j/k direction
> +  int nijk[3] = {pfrom%pijk[0], (pfrom%(pijk[0]*pijk[1]))/pijk[0], pfrom/(pijk[0]*pijk[1])};
> +
> +  for (int i = 0; i < 3; i++) {
> +    if (nijk[i] == pijk[i]-1) top[i] = true;
> +    if (!nijk[i]) bot[i] = true;
> +    if ((!gperiodic[i] && bot[i] && -1 == dijk[i]) || // downward && not periodic
> +        (!gperiodic[i] && top[i] && 1 == dijk[i])) // upward && not periodic
> +      return MB_SUCCESS;
> +  }
> +
> +  std::copy(ldims, ldims+6, facedims);
> +  std::copy(ldims, ldims+6, rdims);
> +  pto = pfrom;
> +  int delijk[3], extra[3];
> +    // nijk_to: rank of pto in i/j/k direction
> +  int nijk_to[3];
> +  for (int i = 0; i < 3; i++) {
> +    delijk[i] = (gdims[i+3] == gdims[i] ? 0 : (gdims[i+3] - gdims[i])/pijk[i]);
> +    extra[i] = (gdims[i+3]-gdims[i]) % delijk[i];
> +    nijk_to[i] = (nijk[i]+dijk[i]+pijk[i]) % pijk[i];
> +  }
> +  pto = nijk_to[2]*pijk[0]*pijk[1] + nijk_to[1]*pijk[0] + nijk_to[0];
> +  assert (pto >= 0 && pto < np);
> +  for (int i = 0; i < 3; i++) {
> +    if (0 != dijk[i]) {
> +      if (-1 == dijk[i]) {
> +        facedims[i+3] = facedims[i];
> +        if (bot[i]) {
> +            // going across lower periodic bdy in i
> +          rdims[i+3] = gdims[i+3]+1; // +1 because ldims[4] on remote proc is gdims[4]+1
> +          across_bdy[i] = -1;
> +        }
> +        else {
> +          rdims[i+3] = ldims[i];
> +        }
> +        rdims[i] = rdims[i+3] - delijk[i];
> +        if (nijk[i] < extra[i]) rdims[i]--;
> +      }
> +      else {
> +        if (top[i]) {
> +          // going across upper periodic bdy in i
> +          rdims[i] = gdims[i];
> +          facedims[i+3] = gdims[i];
> +          across_bdy[i] = 1;
> +        }
> +        else {
> +          rdims[i] = ldims[i+3];
> +        }
> +        facedims[i] = facedims[i+3];
> +        rdims[i+3] = rdims[i] + delijk[i];
> +        if (nijk[i] < extra[i]) rdims[i+3]++;
> +        if (gperiodic[i] && nijk[i] == dijk[i]-2) rdims[i+3]++; // +1 because next proc is on periodic bdy
> +      }
> +    }
> +  }
> +
> +  assert(-1 != pto);
> +#ifndef NDEBUG
> +  for (int i = 0; i < 3; i++) {
> +    assert((rdims[i] >= gdims[i] && (rdims[i+3] <= gdims[i+3] || (across_bdy[i] && bot[i]))));
> +    assert(((facedims[i] >= rdims[i]  || (gperiodic[i] && rdims[i+3] == gdims[i+3] && facedims[i] == gdims[i]))));
> +    assert((facedims[i] >= ldims[i] && facedims[i+3] <= ldims[i+3]));
> +  }
> +#endif
> +
> +  return MB_SUCCESS;
> +}
> +
>  ErrorCode ScdInterface::get_neighbor_alljorkori(int np, int pfrom,
>                                                  const int * const gdims, const int * const gperiodic, const int * const dijk,
>                                                  int &pto, int *rdims, int *facedims, int *across_bdy)
> @@ -1038,7 +1092,7 @@ ErrorCode ScdInterface::get_neighbor_alljorkori(int np, int pfrom,
>    if (MB_SUCCESS != rval) return rval;
>
>    int ind = -1;
> -  across_bdy[0] = across_bdy[1] = 0;
> +  across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
>
>    for (int i = 0; i < 3; i++) {
>      if (pijk[i] > 1) {
> @@ -1108,7 +1162,6 @@ ErrorCode ScdInterface::get_neighbor_alljorkori(int np, int pfrom,
>    assert(-1 == pto || (facedims[2] >= ldims[2] && facedims[5] <= ldims[5]));
>
>    return rval;
> -#endif
>  }
>
>    //! get shared vertices for alljorkori partition scheme
> @@ -1126,7 +1179,7 @@ ErrorCode ScdInterface::get_shared_vertices(ParallelComm *pcomm, ScdBox *box,
>      // get index of partitioned dimension
>    const int *ldims = box->box_dims();
>    ErrorCode rval;
> -  int ijkrem[6], ijkface[6], across_bdy[2];
> +  int ijkrem[6], ijkface[6], across_bdy[3];
>
>    for (int k = -1; k <= 1; k ++) {
>      for (int j = -1; j <= 1; j ++) {
>
> diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
> index d28c824..0fca661 100644
> --- a/src/io/NCHelper.cpp
> +++ b/src/io/NCHelper.cpp
> @@ -4,6 +4,8 @@
>  #include "NCHelperHOMME.hpp"
>  #include "NCHelperMPAS.hpp"
>
> +#include <sstream>
> +
>  #include "moab/ReadUtilIface.hpp"
>  #include "MBTagConventions.hpp"
>
> @@ -15,7 +17,7 @@
>
>  namespace moab {
>
> -NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts)
> +NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
>  {
>    // Check if CF convention is being followed
>    bool is_CF = false;
> @@ -37,107 +39,273 @@ NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions&
>
>    if (is_CF) {
>      if (NCHelperEuler::can_read_file(readNC, fileId))
> -      return new (std::nothrow) NCHelperEuler(readNC, fileId);
> +      return new (std::nothrow) NCHelperEuler(readNC, fileId, opts, fileSet);
>      else if (NCHelperFV::can_read_file(readNC, fileId))
> -      return new (std::nothrow) NCHelperFV(readNC, fileId);
> +      return new (std::nothrow) NCHelperFV(readNC, fileId, opts, fileSet);
>      else if (NCHelperHOMME::can_read_file(readNC, fileId))
> -      return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
> +      return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts, fileSet);
>    }
>    else {
> -    if (NCHelperMPAS::can_read_file(readNC, fileId))
> -      return new (std::nothrow) NCHelperMPAS(readNC, fileId, opts);
> +    if (NCHelperMPAS::can_read_file(readNC))
> +      return new (std::nothrow) NCHelperMPAS(readNC, fileId, opts, fileSet);
>    }
>
>    // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
>    return NULL;
>  }
>
> -ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
> -{
> +ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums) {
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  std::vector<std::string>& dimNames = _readNC->dimNames;
>    std::vector<int>& dimVals = _readNC->dimVals;
> -  int tDim = _readNC->tDim;
> +  std::map<std::string, ReadNC::AttData>& globalAtts = _readNC->globalAtts;
> +  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
>    DebugOutput& dbgOut = _readNC->dbgOut;
> +  int& partMethod = _readNC->partMethod;
> +  ScdInterface* scdi = _readNC->scdi;
> +
> +  ErrorCode rval;
> +  std::string tag_name;
> +
> +  // <__NUM_DIMS>
> +  Tag numDimsTag = 0;
> +  tag_name = "__NUM_DIMS";
> +  int numDims = dimNames.size();
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 1, MB_TYPE_INTEGER, numDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +  ERRORR(rval, "Trouble creating __NUM_DIMS tag.");
> +  rval = mbImpl->tag_set_data(numDimsTag, &_fileSet, 1, &numDims);
> +  ERRORR(rval, "Trouble setting data for __NUM_DIMS tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__NUM_VARS>
> +  Tag numVarsTag = 0;
> +  tag_name = "__NUM_VARS";
> +  int numVars = varInfo.size();
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 1, MB_TYPE_INTEGER, numVarsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +  ERRORR(rval, "Trouble creating __NUM_VARS tag.");
> +  rval = mbImpl->tag_set_data(numVarsTag, &_fileSet, 1, &numVars);
> +  ERRORR(rval, "Trouble setting data for __NUM_VARS tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__DIM_NAMES>
> +  Tag dimNamesTag = 0;
> +  tag_name = "__DIM_NAMES";
> +  std::string dimnames;
> +  unsigned int dimNamesSz = dimNames.size();
> +  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> +    dimnames.append(dimNames[i]);
> +    dimnames.push_back('\0');
> +  }
> +  int dimnamesSz = dimnames.size();
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __DIM_NAMES tag.");
> +  const void* ptr = dimnames.c_str();
> +  rval = mbImpl->tag_set_by_ptr(dimNamesTag, &_fileSet, 1, &ptr, &dimnamesSz);
> +  ERRORR(rval, "Trouble setting data for __DIM_NAMES tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__DIM_VALUES>
> +  Tag dimValsTag = 0;
> +  tag_name = "__DIM_VALUES";
> +  int dimValsSz = (int)dimVals.size();
> +
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_INTEGER, dimValsTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __DIM_VALUES tag.");
> +  ptr = &(dimVals[0]);
> +  rval = mbImpl->tag_set_by_ptr(dimValsTag, &_fileSet, 1, &ptr, &dimValsSz);
> +  ERRORR(rval, "Trouble setting data for __DIM_VALUES tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__VAR_NAMES>
> +  Tag varNamesTag = 0;
> +  tag_name = "__VAR_NAMES";
> +  std::string varnames;
> +  std::map<std::string, ReadNC::VarData>::iterator mapIter;
> +  for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
> +    varnames.append(mapIter->first);
> +    varnames.push_back('\0');
> +  }
> +  int varnamesSz = varnames.size();
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __VAR_NAMES tag.");
> +  ptr = varnames.c_str();
> +  rval = mbImpl->tag_set_by_ptr(varNamesTag, &_fileSet, 1, &ptr, &varnamesSz);
> +  ERRORR(rval, "Trouble setting data for __VAR_NAMES tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // __<dim_name>_LOC_MINMAX
> +  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> +    if (dimNames[i] == "time") {
> +      std::stringstream ss_tag_name;
> +      ss_tag_name << "__" << dimNames[i] << "_LOC_MINMAX";
> +      tag_name = ss_tag_name.str();
> +      Tag tagh = 0;
> +      std::vector<int> val(2, 0);
> +      val[0] = 0;
> +      val[1] = nTimeSteps - 1;
> +      rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> +      ERRORR(rval, "Trouble creating __<dim_name>_LOC_MINMAX tag.");
> +      rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> +      ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_MINMAX tag.");
> +      if (MB_SUCCESS == rval)
> +        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +    }
> +  }
>
> -  ErrorCode rval = MB_SUCCESS;
> -
> -  for (unsigned int i = 0; i < vdatas.size(); i++) {
> -    if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim) != vdatas[i].varDims.end()))
> -      vdatas[i].has_t = true;
> -
> -    for (unsigned int t = 0; t < tstep_nums.size(); t++) {
> -      dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
> -
> -      // get the tag to read into
> -      if (!vdatas[i].varTags[t]) {
> -        rval = _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[i].varTags[t]);
> -        ERRORR(rval, "Trouble getting tag.");
> -      }
> +  // __<dim_name>_LOC_VALS
> +  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> +    if (dimNames[i] != "time")
> +      continue;
> +    std::vector<int> val;
> +    if (!tstep_nums.empty())
> +      val = tstep_nums;
> +    else {
> +      val.resize(tVals.size());
> +      for (unsigned int j = 0; j != tVals.size(); ++j)
> +        val[j] = j;
> +    }
> +    Tag tagh = 0;
> +    std::stringstream ss_tag_name;
> +    ss_tag_name << "__" << dimNames[i] << "_LOC_VALS";
> +    tag_name = ss_tag_name.str();
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), val.size(), MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> +    ERRORR(rval, "Trouble creating __<dim_name>_LOC_VALS tag.");
> +    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_VALS tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +  }
>
> -      // assume point-based values for now?
> -      if (-1 == tDim || dimVals[tDim] <= (int) t)
> -        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
> +  // __<var_name>_DIMS
> +  for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
> +    Tag varNamesDimsTag = 0;
> +    std::stringstream ss_tag_name;
> +    ss_tag_name << "__" << mapIter->first << "_DIMS";
> +    tag_name = ss_tag_name.str();
> +    unsigned int varDimSz = varInfo[mapIter->first].varDims.size();
> +    if (varDimSz == 0)
> +      continue;
> +    varInfo[mapIter->first].varTags.resize(varDimSz, 0);
> +    for (unsigned int i = 0; i != varDimSz; ++i) {
> +      Tag tmptag = 0;
> +      std::string tmptagname = dimNames[varInfo[mapIter->first].varDims[i]];
> +      mbImpl->tag_get_handle(tmptagname.c_str(), 0, MB_TYPE_OPAQUE, tmptag, MB_TAG_ANY);
> +      varInfo[mapIter->first].varTags[i] = tmptag;
> +    }
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), varDimSz, MB_TYPE_HANDLE, varNamesDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +    ERRORR(rval, "Trouble creating __<var_name>_DIMS tag.");
> +    rval = mbImpl->tag_set_data(varNamesDimsTag, &_fileSet, 1, &(varInfo[mapIter->first].varTags[0]));
> +    ERRORR(rval, "Trouble setting data for __<var_name>_DIMS tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +  }
>
> -      // set up the dimensions and counts
> -      // first variable dimension is time, if it exists
> -      if (vdatas[i].has_t)
> -      {
> -        if (vdatas[i].varDims.size() != 1)
> -        {
> -          vdatas[i].readStarts[t].push_back(tstep_nums[t]);
> -          vdatas[i].readCounts[t].push_back(1);
> -        }
> -        else
> -        {
> -          vdatas[i].readStarts[t].push_back(0);
> -          vdatas[i].readCounts[t].push_back(tstep_nums.size());
> -        }
> -      }
> +  // <PARTITION_METHOD>
> +  Tag part_tag = scdi->part_method_tag();
> +  if (!part_tag)
> +    ERRORR(MB_FAILURE, "Trouble getting partition method tag.");
> +  rval = mbImpl->tag_set_data(part_tag, &_fileSet, 1, &partMethod);
> +  ERRORR(rval, "Trouble setting data for PARTITION_METHOD tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__GLOBAL_ATTRIBS>
> +  tag_name = "__GLOBAL_ATTRIBS";
> +  Tag globalAttTag = 0;
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __GLOBAL_ATTRIBS tag.");
> +  std::string gattVal;
> +  std::vector<int> gattLen;
> +  rval = create_attrib_string(globalAtts, gattVal, gattLen);
> +  ERRORR(rval, "Trouble creating attribute strings.");
> +  const void* gattptr = gattVal.c_str();
> +  int globalAttSz = gattVal.size();
> +  rval = mbImpl->tag_set_by_ptr(globalAttTag, &_fileSet, 1, &gattptr, &globalAttSz);
> +  ERRORR(rval, "Trouble setting data for __GLOBAL_ATTRIBS tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__GLOBAL_ATTRIBS_LEN>
> +  tag_name = "__GLOBAL_ATTRIBS_LEN";
> +  Tag globalAttLenTag = 0;
> +  if (gattLen.size() == 0)
> +    gattLen.push_back(0);
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), gattLen.size(), MB_TYPE_INTEGER, globalAttLenTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +  ERRORR(rval, "Trouble creating __GLOBAL_ATTRIBS_LEN tag.");
> +  rval = mbImpl->tag_set_data(globalAttLenTag, &_fileSet, 1, &gattLen[0]);
> +  ERRORR(rval, "Trouble setting data for __GLOBAL_ATTRIBS_LEN tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // __<var_name>_ATTRIBS and __<var_name>_ATTRIBS_LEN
> +  for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
> +    std::stringstream ssTagName;
> +    ssTagName << "__" << mapIter->first << "_ATTRIBS";
> +    tag_name = ssTagName.str();
> +    Tag varAttTag = 0;
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +    ERRORR(rval, "Trouble creating __<var_name>_ATTRIBS tag.");
> +    std::string varAttVal;
> +    std::vector<int> varAttLen;
> +    rval = create_attrib_string(mapIter->second.varAtts, varAttVal, varAttLen);
> +    ERRORR(rval, "Trouble creating attribute strings.");
> +    const void* varAttPtr = varAttVal.c_str();
> +    int varAttSz = varAttVal.size();
> +    rval = mbImpl->tag_set_by_ptr(varAttTag, &_fileSet, 1, &varAttPtr, &varAttSz);
> +    ERRORR(rval, "Trouble setting data for __<var_name>_ATTRIBS tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +    if (varAttLen.size() == 0)
> +      varAttLen.push_back(0);
> +    ssTagName << "_LEN";
> +    tag_name = ssTagName.str();
> +    Tag varAttLenTag = 0;
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), varAttLen.size(), MB_TYPE_INTEGER, varAttLenTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +    ERRORR(rval, "Trouble creating __<var_name>_ATTRIBS_LEN tag.");
> +    rval = mbImpl->tag_set_data(varAttLenTag, &_fileSet, 1, &varAttLen[0]);
> +    ERRORR(rval, "Trouble setting data for __<var_name>_ATTRIBS_LEN tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +  }
>
> -      // Set up other dimensions and counts
> -      if (vdatas[i].varDims.empty()) {
> -        // Scalar variable
> -        vdatas[i].readStarts[t].push_back(0);
> -        vdatas[i].readCounts[t].push_back(1);
> -      }
> -      else {
> -        for (unsigned int idx = 0; idx != vdatas[i].varDims.size(); idx++){
> -          if (tDim != vdatas[i].varDims[idx]){
> -            // Push other variable dimensions, except time, which was already pushed
> -            vdatas[i].readStarts[t].push_back(0);
> -            vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[idx]]);
> -          }
> -        }
> -      }
> -      std::size_t sz = 1;
> -      for (std::size_t idx = 0; idx != vdatas[i].readCounts[t].size(); idx++)
> -        sz *= vdatas[i].readCounts[t][idx];
> -      vdatas[i].sz = sz;
> -      switch (vdatas[i].varDataType) {
> -        case NC_BYTE:
> -        case NC_CHAR:
> -          vdatas[i].varDatas[t] = new char[sz];
> -          break;
> -        case NC_DOUBLE:
> -        case NC_FLOAT:
> -          vdatas[i].varDatas[t] = new double[sz];
> -          break;
> -        case NC_INT:
> -        case NC_SHORT:
> -          vdatas[i].varDatas[t] = new int[sz];
> -          break;
> -        default:
> -          std::cerr << "Unrecognized data type for tag " << std::endl;
> -          rval = MB_FAILURE;
> -      }
> -      if (vdatas[i].varDims.size() <= 1)
> -        break;
> -    }
> +  // <__VAR_NAMES_LOCATIONS>
> +  tag_name = "__VAR_NAMES_LOCATIONS";
> +  Tag varNamesLocsTag = 0;
> +  std::vector<int> varNamesLocs(varInfo.size());
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), varNamesLocs.size(), MB_TYPE_INTEGER, varNamesLocsTag, MB_TAG_CREAT
> +      | MB_TAG_SPARSE);
> +  ERRORR(rval, "Trouble creating __VAR_NAMES_LOCATIONS tag.");
> +  for (mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter) {
> +    varNamesLocs[std::distance(varInfo.begin(), mapIter)] = mapIter->second.entLoc;
>    }
> +  rval = mbImpl->tag_set_data(varNamesLocsTag, &_fileSet, 1, &varNamesLocs[0]);
> +  ERRORR(rval, "Trouble setting data for __VAR_NAMES_LOCATIONS tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +
> +  // <__MESH_TYPE>
> +  Tag meshTypeTag = 0;
> +  tag_name = "__MESH_TYPE";
> +  std::string meshTypeName = get_mesh_type_name();
> +
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __MESH_TYPE tag.");
> +  ptr = meshTypeName.c_str();
> +  int leng= meshTypeName.size();
> +  rval = mbImpl->tag_set_by_ptr(meshTypeTag, &_fileSet, 1, &ptr, &leng);
> +  ERRORR(rval, "Trouble setting data for __MESH_TYPE tag.");
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>
> -  return rval;
> +  return MB_SUCCESS;
>  }
>
> -ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
> +ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;;
>    Interface*& mbImpl = _readNC->mbImpl;
> @@ -146,12 +314,12 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
>    ErrorCode rval = read_variable_to_set_allocate(vdatas, tstep_nums);
>    ERRORR(rval, "Trouble allocating read variables to set.");
>
> -  // finally, read into that space
> +  // Finally, read into that space
>    int success;
>    std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vdatas.size() * tstep_nums.size());
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end() )
> -       continue;// this is a dummy one, we don't have it; we created it for the dummy tag
> +       continue; // This is a dummy one, we don't have it; we created it for the dummy tag
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        void* data = vdatas[i].varDatas[t];
>
> @@ -209,7 +377,7 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
>          break;
>      }
>    }
> -  // debug output, if requested
> +  // Debug output, if requested
>    if (1 == dbgOut.get_verbosity()) {
>      dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
>      for (unsigned int i = 1; i < vdatas.size(); i++)
> @@ -220,7 +388,7 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
> -      ErrorCode tmp_rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
> +      ErrorCode tmp_rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
>        if (MB_SUCCESS != tmp_rval)
>          rval = tmp_rval;
>        if (vdatas[i].varDims.size() <= 1)
> @@ -314,13 +482,305 @@ ErrorCode NCHelper::convert_variable(ReadNC::VarData& var_data, int tstep_num)
>    return MB_SUCCESS;
>  }
>
> -ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle file_set) {
> +ErrorCode NCHelper::read_coordinate(const char* var_name, int lmin, int lmax, std::vector<double>& cvals)
> +{
> +  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
> +  std::map<std::string, ReadNC::VarData>::iterator vmit = varInfo.find(var_name);
> +  if (varInfo.end() == vmit)
> +    return MB_FAILURE;
> +
> +  assert(lmin >= 0 && lmax >= lmin);
> +  NCDF_SIZE tstart = lmin;
> +  NCDF_SIZE tcount = lmax - lmin + 1;
> +  NCDF_DIFF dum_stride = 1;
> +  int fail;
> +
> +  // Check size
> +  if ((std::size_t)tcount != cvals.size())
> +    cvals.resize(tcount);
> +
> +  // Check to make sure it's a float or double
> +  if (NC_DOUBLE == (*vmit).second.varDataType) {
> +    fail = NCFUNCA(get_vars_double)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &cvals[0]);
> +    if (fail)
> +      ERRORS(MB_FAILURE, "Failed to get coordinate values.");
> +  }
> +  else if (NC_FLOAT == (*vmit).second.varDataType) {
> +    std::vector<float> tcvals(tcount);
> +    fail = NCFUNCA(get_vars_float)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &tcvals[0]);
> +    if (fail)
> +      ERRORS(MB_FAILURE, "Failed to get coordinate values.");
> +    std::copy(tcvals.begin(), tcvals.end(), cvals.begin());
> +  }
> +  else {
> +    ERRORR(MB_FAILURE, "Wrong data type for coordinate variable.");
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelper::get_tag_to_set(ReadNC::VarData& var_data, int tstep_num, Tag& tagh)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  std::ostringstream tag_name;
> +  if ((!var_data.has_t) || (var_data.varDims.size() <= 1))
> +    tag_name << var_data.varName;
> +  else if (!tstep_num) {
> +    std::string tmp_name = var_data.varName + "0";
> +    tag_name << tmp_name.c_str();
> +  }
> +  else
> +    tag_name << var_data.varName << tstep_num;
> +  ErrorCode rval = MB_SUCCESS;
> +  tagh = 0;
> +  switch (var_data.varDataType) {
> +    case NC_BYTE:
> +    case NC_CHAR:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_OPAQUE, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +      break;
> +    case NC_DOUBLE:
> +    case NC_FLOAT:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_DOUBLE, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +      break;
> +    case NC_INT:
> +    case NC_SHORT:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), 0, MB_TYPE_INTEGER, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +      break;
> +    default:
> +      std::cerr << "Unrecognized data type for tag " << tag_name << std::endl;
> +      rval = MB_FAILURE;
> +  }
> +
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.str().c_str());
> +
> +  return rval;
> +}
> +
> +ErrorCode NCHelper::get_tag_to_nonset(ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  std::ostringstream tag_name;
> +  if (!tstep_num) {
> +    std::string tmp_name = var_data.varName + "0";
> +    tag_name << tmp_name.c_str();
> +  }
> +  else
> +    tag_name << var_data.varName << tstep_num;
> +  ErrorCode rval = MB_SUCCESS;
> +  tagh = 0;
> +  switch (var_data.varDataType) {
> +    case NC_BYTE:
> +    case NC_CHAR:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_OPAQUE, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
> +      break;
> +    case NC_DOUBLE:
> +    case NC_FLOAT:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
> +      break;
> +    case NC_INT:
> +    case NC_SHORT:
> +      rval = mbImpl->tag_get_handle(tag_name.str().c_str(), num_lev, MB_TYPE_INTEGER, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
> +      break;
> +    default:
> +      std::cerr << "Unrecognized data type for tag " << tag_name.str() << std::endl;
> +      rval = MB_FAILURE;
> +  }
> +
> +  if (MB_SUCCESS == rval)
> +    dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.str().c_str());
> +
> +  return rval;
> +}
> +
> +ErrorCode NCHelper::create_attrib_string(const std::map<std::string, ReadNC::AttData>& attMap, std::string& attVal, std::vector<int>& attLen)
> +{
> +  int success;
> +  std::stringstream ssAtt;
> +  unsigned int sz = 0;
> +  std::map<std::string, ReadNC::AttData>::const_iterator attIt = attMap.begin();
> +  for (; attIt != attMap.end(); ++attIt) {
> +    ssAtt << attIt->second.attName;
> +    ssAtt << '\0';
> +    void* attData = NULL;
> +    switch (attIt->second.attDataType) {
> +      case NC_BYTE:
> +      case NC_CHAR:
> +        sz = attIt->second.attLen;
> +        attData = (char *) malloc(sz);
> +        success = NCFUNC(get_att_text)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (char*) attData);
> +        ERRORS(success, "Failed to read attribute char data.");
> +        ssAtt << "char;";
> +        break;
> +      case NC_DOUBLE:
> +        sz = attIt->second.attLen * sizeof(double);
> +        attData = (double *) malloc(sz);
> +        success = NCFUNC(get_att_double)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (double*) attData);
> +        ERRORS(success, "Failed to read attribute double data.");
> +        ssAtt << "double;";
> +        break;
> +      case NC_FLOAT:
> +        sz = attIt->second.attLen * sizeof(float);
> +        attData = (float *) malloc(sz);
> +        success = NCFUNC(get_att_float)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (float*) attData);
> +        ERRORS(success, "Failed to read attribute float data.");
> +        ssAtt << "float;";
> +        break;
> +      case NC_INT:
> +        sz = attIt->second.attLen * sizeof(int);
> +        attData = (int *) malloc(sz);
> +        success = NCFUNC(get_att_int)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (int*) attData);
> +        ERRORS(success, "Failed to read attribute int data.");
> +        ssAtt << "int;";
> +        break;
> +      case NC_SHORT:
> +        sz = attIt->second.attLen * sizeof(short);
> +        attData = (short *) malloc(sz);
> +        success = NCFUNC(get_att_short)(_fileId, attIt->second.attVarId, attIt->second.attName.c_str(), (short*) attData);
> +        ERRORS(success, "Failed to read attribute short data.");
> +        ssAtt << "short;";
> +        break;
> +      default:
> +        success = 1;
> +    }
> +    char* tmpc = (char *) attData;
> +    for (unsigned int counter = 0; counter != sz; ++counter)
> +      ssAtt << tmpc[counter];
> +    free(attData);
> +    ssAtt << ';';
> +    attLen.push_back(ssAtt.str().size() - 1);
> +  }
> +  attVal = ssAtt.str();
> +
> +  return MB_SUCCESS;
> +}
> +
> +void NCHelper::init_dims_with_no_cvars_info()
> +{
> +  std::vector<std::string>& dimNames = _readNC->dimNames;
> +  std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
> +  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  // Hack: look at all dimensions, and see if we have one that does not appear in the list of varInfo names
> +  // right now, candidates are ncol and nbnd
> +  // for them, create dummy tags
> +  for (unsigned int i = 0; i < dimNames.size(); i++)
> +  {
> +    // If there is a var with this name, skip, we are fine; if not, create a varInfo...
> +    if (varInfo.find(dimNames[i]) != varInfo.end())
> +      continue; // We already have a variable with this dimension name
> +
> +    int sizeTotalVar = varInfo.size();
> +    std::string var_name(dimNames[i]);
> +    ReadNC::VarData &data = varInfo[var_name];
> +    data.varName = std::string(var_name);
> +    data.varId =sizeTotalVar;
> +    data.varTags.resize(1, 0);
> +    data.varDataType = NC_DOUBLE; // Could be int, actually, but we do not really need the type
> +    data.varDims.resize(1);
> +    data.varDims[0]= (int)i;
> +    data.numAtts=0;
> +    data.entLoc = ReadNC::ENTLOCSET;
> +    dbgOut.tprintf(2, "Dummy varInfo created for dimension %s\n", dimNames[i].c_str());
> +    dummyVarNames.insert(dimNames[i]);
> +  }
> +}
> +
> +ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
> +{
> +  std::vector<int>& dimVals = _readNC->dimVals;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  ErrorCode rval = MB_SUCCESS;
> +
> +  for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim) != vdatas[i].varDims.end()))
> +      vdatas[i].has_t = true;
> +
> +    for (unsigned int t = 0; t < tstep_nums.size(); t++) {
> +      dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
> +
> +      // Get the tag to read into
> +      if (!vdatas[i].varTags[t]) {
> +        rval = get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[i].varTags[t]);
> +        ERRORR(rval, "Trouble getting tag.");
> +      }
> +
> +      // Assume point-based values for now?
> +      if (-1 == tDim || dimVals[tDim] <= (int) t)
> +        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
> +
> +      // Set up the dimensions and counts
> +      // First variable dimension is time, if it exists
> +      if (vdatas[i].has_t)
> +      {
> +        if (vdatas[i].varDims.size() != 1)
> +        {
> +          vdatas[i].readStarts[t].push_back(tstep_nums[t]);
> +          vdatas[i].readCounts[t].push_back(1);
> +        }
> +        else
> +        {
> +          vdatas[i].readStarts[t].push_back(0);
> +          vdatas[i].readCounts[t].push_back(tstep_nums.size());
> +        }
> +      }
> +
> +      // Set up other dimensions and counts
> +      if (vdatas[i].varDims.empty()) {
> +        // Scalar variable
> +        vdatas[i].readStarts[t].push_back(0);
> +        vdatas[i].readCounts[t].push_back(1);
> +      }
> +      else {
> +        for (unsigned int idx = 0; idx != vdatas[i].varDims.size(); idx++){
> +          if (tDim != vdatas[i].varDims[idx]){
> +            // Push other variable dimensions, except time, which was already pushed
> +            vdatas[i].readStarts[t].push_back(0);
> +            vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[idx]]);
> +          }
> +        }
> +      }
> +      std::size_t sz = 1;
> +      for (std::size_t idx = 0; idx != vdatas[i].readCounts[t].size(); idx++)
> +        sz *= vdatas[i].readCounts[t][idx];
> +      vdatas[i].sz = sz;
> +      switch (vdatas[i].varDataType) {
> +        case NC_BYTE:
> +        case NC_CHAR:
> +          vdatas[i].varDatas[t] = new char[sz];
> +          break;
> +        case NC_DOUBLE:
> +        case NC_FLOAT:
> +          vdatas[i].varDatas[t] = new double[sz];
> +          break;
> +        case NC_INT:
> +        case NC_SHORT:
> +          vdatas[i].varDatas[t] = new int[sz];
> +          break;
> +        default:
> +          std::cerr << "Unrecognized data type for tag " << std::endl;
> +          rval = MB_FAILURE;
> +      }
> +      if (vdatas[i].varDims.size() <= 1)
> +        break;
> +    }
> +  }
> +
> +  return rval;
> +}
> +
> +ErrorCode ScdNCHelper::check_existing_mesh() {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  int (&lDims)[6] = _readNC->lDims;
>
>    // Get the number of vertices
>    int num_verts;
> -  ErrorCode rval = mbImpl->get_number_entities_by_dimension(file_set, 0, num_verts);
> +  ErrorCode rval = mbImpl->get_number_entities_by_dimension(_fileSet, 0, num_verts);
>    ERRORR(rval, "Trouble getting number of vertices.");
>
>    /*
> @@ -337,7 +797,7 @@ ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle file_set) {
>
>    // Check the number of elements too
>    int num_elems;
> -  rval = mbImpl->get_number_entities_by_dimension(file_set, (-1 == lDims[2] ? 2 : 3), num_elems);
> +  rval = mbImpl->get_number_entities_by_dimension(_fileSet, (-1 == lDims[2] ? 2 : 3), num_elems);
>    ERRORR(rval, "Trouble getting number of elements.");
>
>    /*
> @@ -355,18 +815,12 @@ ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle file_set) {
>    return MB_SUCCESS;
>  }
>
> -ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& faces)
> +ErrorCode ScdNCHelper::create_mesh(Range& faces)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  int (&gDims)[6] = _readNC->gDims;
> -  int (&lDims)[6] = _readNC->lDims;
> -  std::vector<double>& ilVals = _readNC->ilVals;
> -  std::vector<double>& jlVals = _readNC->jlVals;
> -  std::vector<double>& klVals = _readNC->klVals;
>    Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
>    DebugOutput& dbgOut = _readNC->dbgOut;
> -  int (&locallyPeriodic)[2] = _readNC->locallyPeriodic;
> -  int (&globallyPeriodic)[2] = _readNC->globallyPeriodic;
> +  ScdInterface* scdi = _readNC->scdi;
>    ScdParData& parData = _readNC->parData;
>
>    Range tmp_range;
> @@ -380,7 +834,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts,
>    tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1);
>    tmp_range.insert(scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1);
>    tmp_range.insert(scd_box->box_set());
> -  rval = mbImpl->add_entities(file_set, tmp_range);
> +  rval = mbImpl->add_entities(_fileSet, tmp_range);
>    ERRORR(rval, "Couldn't add new vertices to file set.");
>
>    dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_elements(), scd_box->num_vertices());
> @@ -406,7 +860,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts,
>    int di = gDims[3] - gDims[0] + 1;
>    int dj = gDims[4] - gDims[1] + 1;
>    assert(dil == (int)ilVals.size() && djl == (int)jlVals.size() &&
> -      (-1 == lDims[2] || lDims[5]-lDims[2]+1 == (int)klVals.size()));
> +      (-1 == lDims[2] || lDims[5]-lDims[2] + 1 == (int)levVals.size()));
>  #define INDEX(i, j, k) ()
>    for (kl = lDims[2]; kl <= lDims[5]; kl++) {
>      k = kl - lDims[2];
> @@ -417,7 +871,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts,
>          unsigned int pos = i + j * dil + k * dil * djl;
>          xc[pos] = ilVals[i];
>          yc[pos] = jlVals[j];
> -        zc[pos] = (-1 == lDims[2] ? 0.0 : klVals[k]);
> +        zc[pos] = (-1 == lDims[2] ? 0.0 : levVals[k]);
>          itmp = (!locallyPeriodic[0] && globallyPeriodic[0] && il == gDims[3] ? gDims[0] : il);
>          *gid_data = (-1 != kl ? kl * di * dj : 0) + jl * di + itmp + 1;
>          gid_data++;
> @@ -436,7 +890,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts,
>    dbgOut.tprintf(1, "Vertex gids %d-%d\n", vmin, vmax);
>  #endif
>
> -  // add elements to the range passed in
> +  // Add elements to the range passed in
>    faces.insert(scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1);
>
>    if (2 <= dbgOut.get_verbosity()) {
> @@ -459,7 +913,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& opts,
>    return MB_SUCCESS;
>  }
>
> -ErrorCode ScdNCHelper::read_variables(EntityHandle file_set, std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
> +ErrorCode ScdNCHelper::read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
>  {
>    std::vector<ReadNC::VarData> vdatas;
>    std::vector<ReadNC::VarData> vsetdatas;
> @@ -467,17 +921,17 @@ ErrorCode ScdNCHelper::read_variables(EntityHandle file_set, std::vector<std::st
>    ErrorCode rval = read_scd_variable_setup(var_names, tstep_nums, vdatas, vsetdatas);
>    ERRORR(rval, "Trouble setting up read variable.");
>
> -  // create COORDS tag for quads
> -  rval = _readNC->create_quad_coordinate_tag(file_set);
> +  // Create COORDS tag for quads
> +  rval = create_quad_coordinate_tag();
>    ERRORR(rval, "Trouble creating coordinate tags to entities quads");
>
>    if (!vsetdatas.empty()) {
> -    rval = read_variable_to_set(file_set, vsetdatas, tstep_nums);
> +    rval = read_variable_to_set(vsetdatas, tstep_nums);
>      ERRORR(rval, "Trouble read variables to set.");
>    }
>
>    if (!vdatas.empty()) {
> -    rval = read_scd_variable_to_nonset(file_set, vdatas, tstep_nums);
> +    rval = read_scd_variable_to_nonset(vdatas, tstep_nums);
>      ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
>    }
>
> @@ -488,14 +942,6 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
>                                                 std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
>  {
>    std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
> -  int& tMin = _readNC->tMin;
> -  int& tMax = _readNC->tMax;
> -  int& iDim = _readNC->iDim;
> -  int& jDim = _readNC->jDim;
> -  int& tDim = _readNC->tDim;
> -  int& iCDim = _readNC->iCDim;
> -  int& jCDim = _readNC->jCDim;
> -
>    std::map<std::string, ReadNC::VarData>::iterator mit;
>
>    // If empty read them all
> @@ -536,9 +982,9 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
>      }
>    }
>
> -  if (tstep_nums.empty() && -1 != tMin) {
> -    // no timesteps input, get them all
> -    for (int i = tMin; i <= tMax; i++)
> +  if (tstep_nums.empty() && nTimeSteps > 0) {
> +    // No timesteps input, get them all
> +    for (int i = 0; i < nTimeSteps; i++)
>        tstep_nums.push_back(i);
>    }
>    if (!tstep_nums.empty()) {
> @@ -568,72 +1014,55 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
>    return MB_SUCCESS;
>  }
>
> -ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
> +ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  std::vector<std::string>& dimNames = _readNC->dimNames;
>    std::vector<int>& dimVals = _readNC->dimVals;
> -  int (&lDims)[6] = _readNC->lDims;
> -  int (&lCDims)[6] = _readNC->lCDims;
> -  int& tDim = _readNC->tDim;
>    DebugOutput& dbgOut = _readNC->dbgOut;
> -  bool& isParallel = _readNC->isParallel;
> - #ifdef USE_MPI
> -  ParallelComm*& myPcomm = _readNC->myPcomm;
> -#endif
>
>    ErrorCode rval = MB_SUCCESS;
>
>    Range* range = NULL;
>
> -  // get vertices in set
> +  // Get vertices in set
>    Range verts;
> -  rval = mbImpl->get_entities_by_dimension(file_set, 0, verts);
> +  rval = mbImpl->get_entities_by_dimension(_fileSet, 0, verts);
>    ERRORR(rval, "Trouble getting vertices in set.");
>    assert("Should only have a single vertex subrange, since they were read in one shot" &&
>        verts.psize() == 1);
>
>    Range edges;
> -  rval = mbImpl->get_entities_by_dimension(file_set, 1, edges);
> +  rval = mbImpl->get_entities_by_dimension(_fileSet, 1, edges);
>    ERRORR(rval, "Trouble getting edges in set.");
>
>    // Get faces in set
>    Range faces;
> -  rval = mbImpl->get_entities_by_dimension(file_set, 2, faces);
> +  rval = mbImpl->get_entities_by_dimension(_fileSet, 2, faces);
>    ERRORR(rval, "Trouble getting faces in set.");
>    assert("Should only have a single face subrange, since they were read in one shot" &&
>        faces.psize() == 1);
>
>  #ifdef USE_MPI
>    moab::Range faces_owned;
> -  if (isParallel)
> -  {
> +  bool& isParallel = _readNC->isParallel;
> +  if (isParallel) {
> +    ParallelComm*& myPcomm = _readNC->myPcomm;
>      rval = myPcomm->filter_pstatus(faces, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &faces_owned);
>      ERRORR(rval, "Trouble getting owned faces in set.");
>    }
>    else
> -    faces_owned = faces; // not running in parallel, but still with MPI
> +    faces_owned = faces; // Not running in parallel, but still with MPI
>  #endif
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    vdatas[i].numLev = nLevels;
> +
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
>
> -      std::vector<std::string>::iterator vit;
> -      int idx_lev = -1;
> -      int idx_ilev = -1;
> -      if ((vit = std::find(dimNames.begin(), dimNames.end(), "lev")) != dimNames.end())
> -        idx_lev = vit - dimNames.begin();
> -      if ((vit = std::find(dimNames.begin(), dimNames.end(), "ilev")) != dimNames.end())
> -        idx_ilev = vit - dimNames.begin();
> -      if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), idx_lev) != vdatas[i].varDims.end())
> -        vdatas[i].numLev = dimVals[idx_lev];
> -      else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), idx_ilev) != vdatas[i].varDims.end())
> -        vdatas[i].numLev = dimVals[idx_ilev];
> -
>        // Get the tag to read into
>        if (!vdatas[i].varTags[t]) {
> -        rval = _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);
> +        rval = get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);
>          ERRORR(rval, "Trouble getting tag.");
>        }
>
> @@ -646,20 +1075,21 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
>        }
>
>        // Set up the dimensions and counts
> -      // First time
> +      // First: time
>        vdatas[i].readStarts[t].push_back(tstep_nums[t]);
>        vdatas[i].readCounts[t].push_back(1);
>
> -      // then z/y/x
> +      // Next: numLev
>        if (vdatas[i].numLev != 1) {
>          vdatas[i].readStarts[t].push_back(0);
>          vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
>        }
>
> +      // Finally: y and x
>        switch (vdatas[i].entLoc) {
>          case ReadNC::ENTLOCVERT:
> -          // vertices
> -          // only structured mesh has j parameter that multiplies i to get total # vertices
> +          // Vertices
> +          // Only structured mesh has j parameter that multiplies i to get total # vertices
>            vdatas[i].readStarts[t].push_back(lDims[1]);
>            vdatas[i].readCounts[t].push_back(lDims[4] - lDims[1] + 1);
>            vdatas[i].readStarts[t].push_back(lDims[0]);
> @@ -674,7 +1104,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
>            ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
>            break;
>          case ReadNC::ENTLOCFACE:
> -          // faces
> +          // Faces
>            vdatas[i].readStarts[t].push_back(lCDims[1]);
>            vdatas[i].readStarts[t].push_back(lCDims[0]);
>            vdatas[i].readCounts[t].push_back(lCDims[4] - lCDims[1] + 1);
> @@ -687,7 +1117,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
>  #endif
>            break;
>          case ReadNC::ENTLOCSET:
> -          // set
> +          // Set
>            break;
>          default:
>            ERRORR(MB_FAILURE, "Unrecognized entity location type.");
> @@ -713,21 +1143,20 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
>    return rval;
>  }
>
> -ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
> +ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
> -  ErrorCode rval = read_scd_variable_to_nonset_allocate(file_set, vdatas, tstep_nums);
> +  ErrorCode rval = read_scd_variable_to_nonset_allocate(vdatas, tstep_nums);
>    ERRORR(rval, "Trouble allocating read variables.");
>
>    // Finally, read into that space
>    int success;
>    std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vdatas.size() * tstep_nums.size());
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    std::size_t sz = vdatas[i].sz;
> +
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
> -      std::size_t sz = 1;
> -      for (std::size_t idx = 0; idx != vdatas[i].readCounts[t].size(); idx++)
> -        sz *= vdatas[i].readCounts[t][idx];
>        void* data = vdatas[i].varDatas[t];
>        size_t ni = vdatas[i].readCounts[t][2];
>        size_t nj = vdatas[i].readCounts[t][3];
> @@ -740,8 +1169,8 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>            success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
>                &tmpchardata[0] NCREQ);
>            if (vdatas[i].numLev != 1)
> -            // switch from k varying slowest to k varying fastest
> -            success = _readNC->kji_to_jik(ni, nj, nk, data, &tmpchardata[0]);
> +            // Switch from k varying slowest to k varying fastest
> +            success = kji_to_jik(ni, nj, nk, data, &tmpchardata[0]);
>            else {
>              for (std::size_t idx = 0; idx != tmpchardata.size(); idx++)
>                ((char*) data)[idx] = tmpchardata[idx];
> @@ -754,8 +1183,8 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>            success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
>                &tmpdoubledata[0] NCREQ);
>            if (vdatas[i].numLev != 1)
> -            // switch from k varying slowest to k varying fastest
> -            success = _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubledata[0]);
> +            // Switch from k varying slowest to k varying fastest
> +            success = kji_to_jik(ni, nj, nk, data, &tmpdoubledata[0]);
>            else {
>              for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
>                ((double*) data)[idx] = tmpdoubledata[idx];
> @@ -769,7 +1198,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>                &tmpfloatdata[0] NCREQ);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
> -            success = _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdata[0]);
> +            success = kji_to_jik(ni, nj, nk, data, &tmpfloatdata[0]);
>            else {
>              for (std::size_t idx = 0; idx != tmpfloatdata.size(); idx++)
>                ((float*) data)[idx] = tmpfloatdata[idx];
> @@ -783,7 +1212,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>                &tmpintdata[0] NCREQ);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
> -            success = _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[0]);
> +            success = kji_to_jik(ni, nj, nk, data, &tmpintdata[0]);
>            else {
>              for (std::size_t idx = 0; idx != tmpintdata.size(); idx++)
>                ((int*) data)[idx] = tmpintdata[idx];
> @@ -797,7 +1226,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>                &tmpshortdata[0] NCREQ);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
> -            success = _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdata[0]);
> +            success = kji_to_jik(ni, nj, nk, data, &tmpshortdata[0]);
>            else {
>              for (std::size_t idx = 0; idx != tmpshortdata.size(); idx++)
>                ((short*) data)[idx] = tmpshortdata[idx];
> @@ -827,7 +1256,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>          rval = tmp_rval;
>      }
>    }
> -  // debug output, if requested
> +  // Debug output, if requested
>    if (1 == dbgOut.get_verbosity()) {
>      dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
>      for (unsigned int i = 1; i < vdatas.size(); i++)
> @@ -838,7 +1267,67 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
>    return rval;
>  }
>
> -ErrorCode UcdNCHelper::read_variables(EntityHandle file_set, std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
> +ErrorCode ScdNCHelper::create_quad_coordinate_tag() {
> +  Interface*& mbImpl = _readNC->mbImpl;
> +
> +  Range ents;
> +  ErrorCode rval = mbImpl->get_entities_by_type(_fileSet, moab::MBQUAD, ents);
> +  ERRORR(rval, "Trouble getting QUAD entity.");
> +
> +  std::size_t numOwnedEnts = 0;
> +#ifdef USE_MPI
> +  Range ents_owned;
> +  bool& isParallel = _readNC->isParallel;
> +  if (isParallel) {
> +    ParallelComm*& myPcomm = _readNC->myPcomm;
> +    rval = myPcomm->filter_pstatus(ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &ents_owned);
> +    ERRORR(rval, "Trouble getting owned QUAD entity.");
> +    numOwnedEnts = ents_owned.size();
> +  }
> +  else
> +  {
> +    numOwnedEnts = ents.size();
> +    ents_owned = ents;
> +  }
> +#else
> +  numOwnedEnts = ents.size();
> +#endif
> +
> +  if (numOwnedEnts == 0)
> +    return MB_SUCCESS;
> +
> +  assert(numOwnedEnts == ilCVals.size() * jlCVals.size());
> +  std::vector<double> coords(numOwnedEnts * 3);
> +  std::size_t pos = 0;
> +  for (std::size_t j = 0; j != jlCVals.size(); ++j) {
> +    for (std::size_t i = 0; i != ilCVals.size(); ++i) {
> +      pos = j * ilCVals.size() * 3 + i * 3;
> +      coords[pos] = ilCVals[i];
> +      coords[pos + 1] = jlCVals[j];
> +      coords[pos + 2] = 0.0;
> +    }
> +  }
> +  std::string tag_name = "COORDS";
> +  Tag tagh = 0;
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
> +  ERRORR(rval, "Trouble creating COORDS tag.");
> +
> +  void *data;
> +  int count;
> +#ifdef USE_MPI
> +  rval = mbImpl->tag_iterate(tagh, ents_owned.begin(), ents_owned.end(), count, data);
> +#else
> +  rval = mbImpl->tag_iterate(tagh, ents.begin(), ents.end(), count, data);
> +#endif
> +  ERRORR(rval, "Failed to get COORDS tag iterator.");
> +  assert(count == (int)numOwnedEnts);
> +  double* quad_data = (double*) data;
> +  std::copy(coords.begin(), coords.end(), quad_data);
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode UcdNCHelper::read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums)
>  {
>    std::vector<ReadNC::VarData> vdatas;
>    std::vector<ReadNC::VarData> vsetdatas;
> @@ -847,18 +1336,17 @@ ErrorCode UcdNCHelper::read_variables(EntityHandle file_set, std::vector<std::st
>    ERRORR(rval, "Trouble setting up read variable.");
>
>    if (!vsetdatas.empty()) {
> -    rval = read_variable_to_set(file_set, vsetdatas, tstep_nums);
> +    rval = read_variable_to_set(vsetdatas, tstep_nums);
>      ERRORR(rval, "Trouble read variables to set.");
>    }
>
>    if (!vdatas.empty()) {
>  #ifdef PNETCDF_FILE
> -    // in serial, we will use the old read, everything is contiguous
> -    // in parallel, we will use async read in pnetcdf
> -    // the other mechanism is not working, forget about it
> -    rval = read_ucd_variable_to_nonset_async(file_set, vdatas, tstep_nums);
> +    // With pnetcdf support, we will use async read
> +    rval = read_ucd_variable_to_nonset_async(vdatas, tstep_nums);
>  #else
> -    rval = read_ucd_variable_to_nonset(file_set, vdatas, tstep_nums);
> +    // Without pnetcdf support, we will use old read
> +    rval = read_ucd_variable_to_nonset(vdatas, tstep_nums);
>  #endif
>      ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
>    }
>
> diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
> index 0ac9b0c..6355141 100644
> --- a/src/io/NCHelper.hpp
> +++ b/src/io/NCHelper.hpp
> @@ -17,49 +17,101 @@ namespace moab {
>  class NCHelper
>  {
>  public:
> -  NCHelper(ReadNC* readNC, int fileId) : _readNC(readNC), _fileId(fileId) {}
> +  NCHelper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
> +:_readNC(readNC), _fileId(fileId), _opts(opts), _fileSet(fileSet),
> +  nTimeSteps(0), nLevels(1), tDim(-1), levDim(-1) {}
>    virtual ~NCHelper() {}
>
>    //! Get appropriate helper instance for ReadNC class
> -  static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts);
> +  static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet);
>
>    //! Interfaces to be implemented in child classes
> -  virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle file_set) = 0;
> -  virtual ErrorCode check_existing_mesh(EntityHandle file_set) = 0;
> -  virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& faces) = 0;
> -  virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std::string>& var_names, std::vector<int>& tstep_nums) = 0;
> +  virtual ErrorCode init_mesh_vals() = 0;
> +  virtual ErrorCode check_existing_mesh() = 0;
> +  virtual ErrorCode create_mesh(Range& faces) = 0;
> +  virtual ErrorCode read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums) = 0;
>    virtual std::string get_mesh_type_name() = 0;
>
> +  //! Create NC conventional tags
> +  ErrorCode create_conventional_tags(const std::vector<int>& tstep_nums);
> +
>  protected:
>    //! Read set variables, common to scd mesh and ucd mesh
> -  ErrorCode read_variable_to_set(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums);
> +  ErrorCode read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums);
>
>    //! Convert variables in place
>    ErrorCode convert_variable(ReadNC::VarData& var_data, int tstep_num);
>
> +  ErrorCode read_coordinate(const char* var_name, int lmin, int lmax,
> +                            std::vector<double>& cvals);
> +
> +  ErrorCode get_tag_to_set(ReadNC::VarData& var_data, int tstep_num, Tag& tagh);
> +
> +  ErrorCode get_tag_to_nonset(ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev);
> +
> +  //! Create a character string attString of attMap.  with '\0'
> +  //! terminating each attribute name, ';' separating the data type
> +  //! and value, and ';' separating one name/data type/value from
> +  //! the next'.  attLen stores the end position for each name/data
> +  //! type/ value.
> +  ErrorCode create_attrib_string(const std::map<std::string, ReadNC::AttData>& attMap,
> +                                 std::string& attString,
> +                                 std::vector<int>& attLen);
> +
> +  //! Init info for dimensions that don't have corresponding
> +  //! coordinate variables - this info is used for creating tags
> +  void init_dims_with_no_cvars_info();
> +
>  private:
>    //! Used by read_variable_to_set()
>    ErrorCode read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums);
>
>  protected:
> +  //! Allow NCHelper to directly access members of ReadNC
>    ReadNC* _readNC;
> +
> +  //! Cache some information from ReadNC
>    int _fileId;
> +  const FileOptions& _opts;
> +  EntityHandle _fileSet;
> +
> +  //! Dimensions of time and level
> +  int nTimeSteps, nLevels;
> +
> +  //! Values for time and level
> +  std::vector<double> tVals, levVals;
> +
> +  //! Dimension numbers for time and level
> +  int tDim, levDim;
>  };
>
>  //! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
>  class ScdNCHelper : public NCHelper
>  {
>  public:
> -  ScdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
> +  ScdNCHelper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
> +: NCHelper(readNC, fileId, opts, fileSet),
> +  iDim(-1), jDim(-1), iCDim(-1), jCDim(-1)
> +  {
> +    for (unsigned int i = 0; i < 6; i++) {
> +      gDims[i] = -1;
> +      lDims[i] = -1;
> +      gCDims[i] = -1;
> +      lCDims[i] = -1;
> +    }
> +
> +    locallyPeriodic[0] = locallyPeriodic[1] = locallyPeriodic[2] = 0;
> +    globallyPeriodic[0] = globallyPeriodic[1] = globallyPeriodic[2] = 0;
> +  }
>    virtual ~ScdNCHelper() {}
>
>  private:
>    //! Implementation of NCHelper::check_existing_mesh()
> -  virtual ErrorCode check_existing_mesh(EntityHandle file_set);
> +  virtual ErrorCode check_existing_mesh();
>    //! Implementation of NCHelper::create_mesh()
> -  virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opts, EntityHandle file_set, Range& faces);
> +  virtual ErrorCode create_mesh(Range& faces);
>    //! Implementation of NCHelper::read_variables()
> -  virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
> +  virtual ErrorCode read_variables(std::vector<std::string>& var_names, std::vector<int>& tstep_nums);
>
>    //! Separate set and non-set variables for scd mesh
>    ErrorCode read_scd_variable_setup(std::vector<std::string>& var_names,
> @@ -68,25 +120,71 @@ private:
>                                      std::vector<ReadNC::VarData>& vsetdatas);
>
>    //! Read non-set variables for scd mesh
> -  ErrorCode read_scd_variable_to_nonset_allocate(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas,
> +  ErrorCode read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
>                                                   std::vector<int>& tstep_nums);
> -  ErrorCode read_scd_variable_to_nonset(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas,
> +  ErrorCode read_scd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas,
>                                          std::vector<int>& tstep_nums);
> +
> +  //! Create COORDS tag for quads coordinate
> +  ErrorCode create_quad_coordinate_tag();
> +
> +  template <typename T> ErrorCode kji_to_jik(size_t ni, size_t nj, size_t nk, void* dest, T* source)
> +  {
> +    size_t nik = ni * nk, nij = ni * nj;
> +    T* tmp_data = reinterpret_cast<T*>(dest);
> +    for (std::size_t j = 0; j != nj; j++)
> +      for (std::size_t i = 0; i != ni; i++)
> +        for (std::size_t k = 0; k != nk; k++)
> +          tmp_data[j*nik + i*nk + k] = source[k*nij + j*ni + i];
> +    return MB_SUCCESS;
> +  }
> +
> +protected:
> +  //! Dimensions of global grid in file
> +  int gDims[6];
> +
> +  //! Dimensions of my local part of grid
> +  int lDims[6];
> +
> +  //! Center dimensions of global grid in file
> +  int gCDims[6];
> +
> +  //! Center dimensions of my local part of grid
> +  int lCDims[6];
> +
> +  //! Values for i/j
> +  std::vector<double> ilVals, jlVals;
> +
> +  //! Center values for i/j
> +  std::vector<double> ilCVals, jlCVals;
> +
> +  //! Dimension numbers for i/j
> +  int iDim, jDim;
> +
> +  //! Center dimension numbers for i/j
> +  int iCDim, jCDim;
> +
> +  //! Whether mesh is locally periodic in i or j
> +  int locallyPeriodic[3];
> +
> +  //! Whether mesh is globally periodic in i or j
> +  int globallyPeriodic[3];
>  };
>
>  //! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
>  class UcdNCHelper : public NCHelper
>  {
>  public:
> -  UcdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId),
> -  cDim(-1), eDim(-1), vDim(-1), levDim(-1),
> +  UcdNCHelper(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
> +: NCHelper(readNC, fileId, opts, fileSet),
>    nCells(0), nEdges(0), nVertices(0),
> -  nLocalCells(0), nLocalEdges(0), nLocalVertices(0) {}
> +  nLocalCells(0), nLocalEdges(0), nLocalVertices(0),
> +  cDim(-1), eDim(-1), vDim(-1) {}
>    virtual ~UcdNCHelper() {}
>
>  private:
>    //! Implementation of NCHelper::read_variables()
> -  virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std::string>& var_names,
> +  virtual ErrorCode read_variables(std::vector<std::string>& var_names,
>                                     std::vector<int> &tstep_nums);
>
>    //! Separate set and non-set variables for ucd mesh (implemented differently in child classes)
> @@ -96,31 +194,55 @@ private:
>                                              std::vector<ReadNC::VarData>& vsetdatas) = 0;
>
>    //! Read non-set variables for ucd mesh (implemented differently in child classes)
> -  virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas,
> +  virtual ErrorCode read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
>                                                           std::vector<int>& tstep_nums) = 0;
>  #ifdef PNETCDF_FILE
> -  virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas,
> +  virtual ErrorCode read_ucd_variable_to_nonset_async(std::vector<ReadNC::VarData>& vdatas,
>                                                        std::vector<int>& tstep_nums) = 0;
>  #else
> -  virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std::vector<ReadNC::VarData>& vdatas,
> +  virtual ErrorCode read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas,
>                                                  std::vector<int>& tstep_nums) = 0;
>  #endif
>
>  protected:
> -  //! Dimension numbers for nCells, nEdges, nVertices, nLevels
> -  int cDim, eDim, vDim, levDim;
> -
> -  //! Coordinate values for vertices
> -  std::vector<double> xVertVals, yVertVals, zVertVals;
> -
> +  //! This version takes as input the moab range, from which we actually need just the
> +  //! size of each sequence, for a proper transpose of the data
> +  template <typename T> ErrorCode kji_to_jik_stride(size_t , size_t nj, size_t nk, void* dest, T* source, Range& localGid)
> +  {
> +    std::size_t idxInSource = 0; // Position of the start of the stride
> +    // For each subrange, we will transpose a matrix of size
> +    // subrange*nj*nk (subrange takes the role of ni)
> +    T* tmp_data = reinterpret_cast<T*>(dest);
> +    for (Range::pair_iterator pair_iter = localGid.pair_begin();
> +        pair_iter != localGid.pair_end(); ++pair_iter) {
> +      std::size_t size_range = pair_iter->second - pair_iter->first + 1;
> +      std::size_t nik = size_range * nk, nij = size_range * nj;
> +      for (std::size_t j = 0; j != nj; j++)
> +        for (std::size_t i = 0; i != size_range; i++)
> +          for (std::size_t k = 0; k != nk; k++)
> +            tmp_data[idxInSource + j*nik + i*nk + k] = source[idxInSource + k*nij + j*size_range + i];
> +      idxInSource += (size_range*nj*nk);
> +    }
> +    return MB_SUCCESS;
> +  }
> +
> +  //! Dimensions of global grid in file
>    int nCells;
>    int nEdges;
>    int nVertices;
>
> +  //! Dimensions of my local part of grid
>    int nLocalCells;
>    int nLocalEdges;
>    int nLocalVertices;
>
> +  //! Coordinate values for vertices
> +  std::vector<double> xVertVals, yVertVals, zVertVals;
> +
> +  //! Dimension numbers for nCells, nEdges and nVertices
> +  int cDim, eDim, vDim;
> +
> +  //! Local global ID for cells, edges and vertices
>    Range localGidCells, localGidEdges, localGidVerts;
>  };
>
>
> This diff is so big that we needed to truncate the remainder.
>
> https://bitbucket.org/fathomteam/moab/commits/c9647cc700b1/
> Changeset:   c9647cc700b1
> Branch:      None
> User:        vijaysm
> Date:        2013-09-06 23:14:03
> Summary:     Merged fathomteam/moab into master
> Affected #:  54 files
>
> diff --git a/.gitignore b/.gitignore
> index 6d29b5e..967aaa7 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -131,10 +131,12 @@ test/obb/obb_time
>  test/obb/obb_tree_tool
>  test/obb_test
>  test/oldinc/test_oldinc
> +test/read_mpas_nc
>  test/parallel/*.h5m
>  test/parallel/*.vtk
>  test/parallel/mbparallelcomm_test
>  test/parallel/mhdf_parallel
> +test/parallel/mpastrvpart
>  test/parallel/par_coupler_test
>  test/parallel/par_intx_sph
>  test/parallel/parallel_hdf5_test
> @@ -158,6 +160,7 @@ test/perf/tstt_perf_binding
>  test/range_test
>  test/reorder_test
>  test/scdseq_test
> +test/scd_test_partn
>  test/seq_man_test
>  test/tag_test
>  test/test_adj
>
> diff --git a/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
> index 8f81cff..d67ca27 100644
> --- a/doc/MetaData/metadata.h
> +++ b/doc/MetaData/metadata.h
> @@ -129,13 +129,13 @@ Data: Entity sets; Tag(s): DIRICHLET_SET/I, NEUMANN_SET/I)
>  Boundary conditions are often specified in terms of geometric model entities, similar to material types.  MOAB uses entity sets to store this information as well.  The DIRICHLET_SET and NEUMANN_SET tags are used to represent Dirichlet- and Neumann-type boundary condition sets, resp.  By convention, Neumann sets usually contain (indirectly) intermediate-dimension entities like edges in a 2D mesh or faces in a 3D mesh, while Dirichlet sets usually contain vertices.  In addition, Neumann sets are represented as sets of faces, rather than as sides of elements.  Faces can be ordered “forward” or “reverse” with respect to one of the bounding elements, depending on whether the right-hand normal points into or out of the element.  Forward-sense faces are added to the Neumann set.  Reverse-sense faces are put into a separate set; that set is tagged with the NEUSET_SENSE tag, with value = -1; and that reverse set is added to the Neummann set.
>
>  <H3> Parallel Mesh Constructs </H3>
> -(Data: Entity sets, entities; Tag(s): PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP)
> +(Data: Entity sets, entities; Tag(s): PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP)
>
>  On a parallel computer, MOAB can represent the mesh on each processor as well as information about entities shared with neighboring processors.  Some of this information is also relevant even when the mesh is represented on a serial machine.  MOAB uses several tag and set conventions to describe the parallel nature of a mesh.  This information is summarized here; for a more complete description of MOAB’s parallel mesh representation and functionality, see [ref-moabpar].
>
>  - <B> Parallel partition, parts </B>
>
> -Most parallel mesh applications use a domain decomposition approach, where each processor solves for a subset of the domain.  The set of entities solved by a given processor is referred to as a part, and the collection of parts together is called the partition.  MOAB stores each part in an entity set, marked with the PARALLEL_PART tag, whose value is the rank of the processor assigned that part; an entity set which contains all part sets is given the PARALLEL_PARTITION tag, whose value is currently meaningless.  The MBZoltan tool included as a tool in MOAB can partition a mesh for parallel solution, and writes the partition to the mesh in the form of parts and partitions.  Both these types of sets can be accessed in a serial mesh, e.g. for visualization.
> +Most parallel mesh applications use a domain decomposition approach, where each processor solves for a subset of the domain.  The set of entities solved by a given processor is referred to as a part, and the collection of parts together is called the partition.  MOAB stores each part in an entity set, marked with the PARALLEL_PARTITION tag, whose value is the rank of the processor assigned that part; an entity set which contains all part sets is given the PARALLEL_PARTITIONING_TAG_NAME tag, whose value is currently meaningless.  The MBZoltan tool included as a tool in MOAB can partition a mesh for parallel solution, and writes the partition to the mesh in the form of parts and partitions.  Both these types of sets can be accessed in a serial mesh, e.g. for visualization.
>
>  - <B> Part interfaces </B>
>
> @@ -273,7 +273,7 @@ GEOM_SENSE_N_SENSES/I*N</td><tr><td>Parallel mesh constructs</td><td>E, S</td>
> -<td>PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP</td>
> +<td>PARALLEL_MESH_PARTITIONING/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP</td><td> Data which describes parallel mesh</td></tr><tr>
> @@ -380,19 +380,19 @@ GEOM_SENSE_N_SENSES/I*N</td><td>Entities or sets with common boundary condition </td></tr><tr>
> -<td>PARALLEL_PART </td>
> +<td>PARALLEL_PARTITION </td><td>I</td><td>S</td><td>Represent a part in a partition</td></tr><tr>
> -<td>PARALLEL_PARTITION</td>
> +<td>PARALLEL_MESH_PARTITIONING</td><td>I</td><td>S</td><td>Represents a partition of the mesh for parallel solution, which is a collection of parts</td></tr><tr>
> -<td>__PARALLEL_SHARED_HANDLEd</td>
> +<td>__PARALLEL_SHARED_HANDLE</td><td>H</td><td>E, S</td><td> Handle of this entity/set on sharing processor</td>
> @@ -619,7 +619,7 @@ various tags representing information read from the file. These tags are describ
>  Reading unstructured NC files in the HOMME format is also supported. Currently a trivial
>  element-based partition is the only option for parallel reading. As the data is unstructured, it is necessary to have a connectivity file to define the vertex adjacencies. The default convention is to have a file called HommeMapping.nc in the same directory as the the variable data file. If this convention is not followed, the connectivity file can be specified with the option -O CONN=”/path/to/connectivity.nc”. An example of mbconvert using the parallel read capability is shown below:
>
> -<B>  mpiexec -np 2 tools/mbconvert -O TRIVIAL_PARTITION -O DEBUG_IO=1 -o DEBUG_IO=9 -o PARALLEL=WRITE_PART /nfs2/hayes6/meshlab/homme_data/camrun.cam2.h0.0000-01-01-16200.nc output.h5m </B>
> +<B>  mpiexec -np 2 tools/mbconvert -O TRIVIAL -O DEBUG_IO=1 -o DEBUG_IO=9 -o PARALLEL=WRITE_PART /nfs2/hayes6/meshlab/homme_data/camrun.cam2.h0.0000-01-01-16200.nc output.h5m </B>
>
>  Several other things to note about reading climate data files into MOAB:
>  - Time-dependent variables: MOAB currently has no mechanism for time-dependent tags. Therefore, time-dependent variables are represented using one tag per timestep, with the tag name set as the variable name plus the timestep index. Thus, the first few timesteps for the variable TEMPERATURE would be represented in tags named TEMPERATURE0, TEMPERATURE1, etc.
> @@ -649,27 +649,33 @@ centered variables correctly.
>  </tr><tr><td>__DIM_NAMES </td>
> -<td>C*var </td>
> -<td>S </td>
> +<td>C*var</td>
> +<td>S</td><td>The dimension names, concatenated into a
>  character string, with '\0' terminating each name.
> - </td>
> +</td>
> +</tr>
> +<tr>
> +<td>__DIM_LENS </td>
> +<td>I*var</td>
> +<td>S</td>
> +<td>A vector of integers, storing the length of
> +each dimension.
> +</td></tr><tr>
> -<td>__DIM_NAMES
> +<td>__VAR_NAMES
>  </td><td>C*var</td><td>S</td>
> -<td>The variable names, concatenated into a character
> -string, with '\0' terminating each name.
> +<td>The variable names, concatenated into a
> +character string, with '\0' terminating each name.
>  </td></tr><tr><td><dim_name></td>
> -<td>(I or
> -D)*va
> -</td>
> +<td>(I or D)*var</td><td>S</td><td>For each dimension, the values for the dimension.
>  The data type for this tag corresponds to that in the
> @@ -677,36 +683,48 @@ netcdf file. The length of this tag is the number of
>  values stored for the dimension in the netcdf file.</td></tr><tr>
> -<td>__<dim_name>_LOC_MIN MAX</td>
> -<td>2*(I or D)</td>
> +<td>__<dim_name>_LOC_MIN_MAX</td>
> +<td>(I or D)*2</td><td>S</td><td>The indices (0-based) of the local min and max
>  values of dimension stored locally. For spatial
>  dimensions like lon or lat, this will store the
> -minimum and maximum indices in the loca</td>
> +minimum and maximum indices in the local partition
> +of the grid. For dimensions like time, where each
> +processor represents the entire dimension, this will
> +likely store 0 and the number of values for that
> +dimension. Only one of __<dim_name>_LOC_VALS and
> +__<dim_name>_LOC_MIN_MAX can be used for a given
> +dimension.</td></tr><tr>
> -<td >__<dim_name>_LOC_VAL </td>
> -<td>(I or D)*var </td>
> +<td>__<dim_name>_LOC_VAL </td>
> +<td>(I or D)*var</td><td>S</td><td>The indices (0-based) of the dimension stored
>  locally. This tag only makes sense for dimensions
>  that can be read in multiple pieces, such as time.
>  Only one of __<dim_name>_LOC_VALS and
> -_LOC_MIN_MAX can be used for a given
> -dimension.
> +__<dim_name>_LOC_MIN_MAX can be used for a given
> +dimension.</td>
> +</tr>
> +<tr>
> +<td>__<dim_name>_GLOBAL_MIN_MAX</td>
> +<td>(I or D)*2</td>
> +<td>S</td>
> +<td>The indices (0-based) of the global min and max
> +values of dimension.</td></tr><tr><td>__<var_name>_DIMS
>  </td>
> -<td>C*n
> +<td>H*n
>  </td><td>S</td>
> -<td>For each variable, the tag handles for the
> -dimensions defining this variable, in netcdf
> -ordering (last dimension varying fastest). The
> -length of this tag, n, is # dimensions for the
> -variable * sizeof(TagHandle).
> +<td>For each variable, this tag stores the tag
> +handles for the n dimensions defining this variable,
> +in netcdf ordering (last dimension varying fastest).
> +The size of this tag is n * sizeof(TagHandle).
>  </td></tr><tr>
> @@ -723,7 +741,7 @@ Timestep index is 0-based.
>  <tr><td>__GLOBAL_ATTRIBS
>  </td>
> -<td>C*Var
> +<td>C*var
>  </td><td>S</td><td>The global attributes, concatenated into a character
> @@ -735,7 +753,7 @@ string, with ‘\0’ terminating each attribute name, ‘;’
>  <tr><td>__GLOBAL_ATTRIBS_LEN
>  </td>
> -<td>I*Var
> +<td>I*var
>  </td><td>S</td><td>A vector of integers, marking the end position of
> @@ -745,7 +763,7 @@ each attribute (name/data type/value) in __GLOBAL_ATTRIBS tag.
>  <tr><td>__<var_name>_ATTRIBS
>  </td>
> -<td>C*Var
> +<td>C*var
>  </td><td>S</td><td>The variable attributes, concatenated into a
> @@ -757,7 +775,7 @@ character string, with ‘\0’ terminating each attribute
>  <tr><td>__<var_name>_ATTRIBS_LEN
>  </td>
> -<td>I*Var
> +<td>I*var
>  </td><td>S</td><td>A vector of integers, marking the end position of
>
> diff --git a/itaps/imesh/MOAB_iMeshP_unit_tests.cpp b/itaps/imesh/MOAB_iMeshP_unit_tests.cpp
> index 29f88a8..96d659d 100644
> --- a/itaps/imesh/MOAB_iMeshP_unit_tests.cpp
> +++ b/itaps/imesh/MOAB_iMeshP_unit_tests.cpp
> @@ -32,11 +32,12 @@ const char* const FILENAME = "iMeshP_test_file";
>
>  #define PCHECK do { ierr = is_any_proc_error(ierr); CHKERR; } while(false)
>
> +// Use my_rank instead of rank to avoid shadowed declaration
>  #define ASSERT(A) do { \
>    if (is_any_proc_error(!(A))) { \
> -    int rank = 0; \
> -    MPI_Comm_rank( MPI_COMM_WORLD, &rank ); \
> -    if (!rank) std::cerr << "Failed assertion: " #A << std::endl \
> +    int my_rank = 0; \
> +    MPI_Comm_rank( MPI_COMM_WORLD, &my_rank ); \
> +    if (0 == my_rank) std::cerr << "Failed assertion: " #A << std::endl \
>                           << "  at " __FILE__ ":" << __LINE__ << std::endl; \
>      return 1; \
>    } } while (false)
> @@ -1684,7 +1685,7 @@ int test_part_boundary_iter( iMesh_Instance imesh, iMeshP_PartitionHandle prtn,
>   * Test:
>   * - iMeshP_getAdjEntities
>   */
> -int test_get_adjacencies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
> +int test_get_adjacencies( iMesh_Instance /* imesh */, iMeshP_PartitionHandle /* prtn */, const PartMap& )
>  {
>    return iBase_SUCCESS;
>  }
> @@ -1695,7 +1696,7 @@ int test_get_adjacencies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, con
>   * - iMeshP_initEntIter
>   * - iMeshP_initEntArrIter
>   */
> -int test_entity_iterator( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& )
> +int test_entity_iterator( iMesh_Instance /*imesh */, iMeshP_PartitionHandle /*prtn*/, const PartMap& )
>  {
>    return iBase_SUCCESS;
>  }
> @@ -1708,7 +1709,7 @@ int test_entity_iterator( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, con
>   * - iMeshP_isEntOwner
>   * - iMeshP_isEntOwnerArr
>   */
> -int test_entity_owner( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
> +int test_entity_owner( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */ )
>  {
>    int ierr, rank, size;
>    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
> @@ -1840,8 +1841,8 @@ int test_entity_owner( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const
>      assert( junk1 == (int)is_owner_list.size() );
>      assert( junk3 == (int)all_entities.size() );
>      invalid_count = 0;
> -    for (size_t i = 0; i < all_entities.size(); ++i) {
> -      if (!(is_owner_list[i]) == (local_ids[0] == all_owners[i]))
> +    for (size_t j = 0; j < all_entities.size(); ++j) {
> +      if (!(is_owner_list[j]) == (local_ids[0] == all_owners[j]))
>          ++invalid_count;
>      }
>    }
> @@ -2166,7 +2167,7 @@ struct VtxCopyData {
>   * - iMeshP_getCopyOnPart
>   * - iMeshP_getOwnerCopy
>   */
> -int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
> +int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */ )
>  {
>    int ierr, rank, size;
>    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
> @@ -2269,11 +2270,12 @@ int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const
>    int num_error = 0, num_incorrect = 0, junk4;
>    for (size_t i = 0; i < local_vertices.size(); ++i) {
>      int num_copies = -1;
> -    iMeshP_Part* part_ids = 0;
> +    //iMeshP_Part* part_ids = 0;
> +    iMeshP_Part* ptr_part_ids = 0; // Use ptr_part_ids to avoid shadowing std::vector<iMeshP_Part> part_ids
>      iBase_EntityHandle* copies = 0;
>      junk2 = junk3 = junk4 = 0;
>      iMeshP_getCopies( imesh, prtn, local_vertices[i],
> -                      &part_ids, &junk2, &num_copies,
> +                      &ptr_part_ids, &junk2, &num_copies,
>                        &copies, &junk3, &junk4, &ierr );
>      if (iBase_SUCCESS != ierr) {
>        ++num_error;
> @@ -2285,13 +2287,13 @@ int test_entity_copies( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const
>      if (num_copies != (int)expected.parts.size())
>        ++num_incorrect;
>      else for (size_t j = 0; j < expected.parts.size(); ++j) {
> -      int idx = std::find( part_ids, part_ids+num_copies, expected.parts[j] ) - part_ids;
> +      int idx = std::find( ptr_part_ids, ptr_part_ids + num_copies, expected.parts[j] ) - ptr_part_ids;
>        if (idx == num_copies || copies[idx] != expected.handles[j]) {
>          ++num_incorrect;
>          break;
>        }
>      }
> -    free(part_ids);
> +    free(ptr_part_ids);
>      free(copies);
>    }
>    ASSERT( 0 == num_error );
> @@ -2461,7 +2463,7 @@ int get_num_adj_all( iMesh_Instance imesh,
>   * Test:
>   * - iMeshP_createGhostEntsAll
>   */
> -int test_create_ghost_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& map )
> +int test_create_ghost_ents( iMesh_Instance imesh, iMeshP_PartitionHandle prtn, const PartMap& /* map */)
>  {
>    int ierr;
>
>
> diff --git a/itaps/imesh/iMeshP_MOAB.cpp b/itaps/imesh/iMeshP_MOAB.cpp
> index ab45811..e554fba 100644
> --- a/itaps/imesh/iMeshP_MOAB.cpp
> +++ b/itaps/imesh/iMeshP_MOAB.cpp
> @@ -350,7 +350,7 @@ void iMeshP_createPartitionAll( iMesh_Instance instance,
>    *partition_handle = 0;
>
>    Tag prtn_tag;
> -  ErrorCode rval = MOABI->tag_get_handle( PARALLEL_PARITIONING_TAG_NAME,
> +  ErrorCode rval = MOABI->tag_get_handle( PARALLEL_PARTITIONING_TAG_NAME,
>                                            1, MB_TYPE_INTEGER,
>                                            prtn_tag,
>                                            MB_TAG_SPARSE|MB_TAG_CREAT );
>
> diff --git a/itaps/imesh/iMesh_MOAB.cpp b/itaps/imesh/iMesh_MOAB.cpp
> index 6d55492..d09fec1 100644
> --- a/itaps/imesh/iMesh_MOAB.cpp
> +++ b/itaps/imesh/iMesh_MOAB.cpp
> @@ -3424,7 +3424,7 @@ void iMesh_createStructuredMesh(iMesh_Instance instance,
>  }
>
>  void iMesh_freeMemory(
> -        iMesh_Instance instance,
> +    iMesh_Instance /*instance*/,
>            /**< [in] iMesh instance handle */
>           void ** ptrToMem)
>  {
>
> diff --git a/src/GeomTopoTool.cpp b/src/GeomTopoTool.cpp
> index a302f0c..8f74453 100644
> --- a/src/GeomTopoTool.cpp
> +++ b/src/GeomTopoTool.cpp
> @@ -901,7 +901,7 @@ ErrorCode GeomTopoTool::geometrize_surface_set(EntityHandle surface, EntityHandl
>
>
>    Skinner tool(mdbImpl);
> -  rval = tool.find_skin(surface_ents, 1, edge_ents);
> +  rval = tool.find_skin(0, surface_ents, 1, edge_ents);
>    if (MB_SUCCESS != rval)
>      return rval;
>    if (debugFlag)
> @@ -1472,7 +1472,7 @@ bool GeomTopoTool::check_model()
>      if (MB_SUCCESS!=rval)
>        RETFALSE(" can't get surface elements from the face set ", faceSet)
>
> -    rval = tool.find_skin(surface_ents, 1, edge_ents);
> +    rval = tool.find_skin(0, surface_ents, 1, edge_ents);
>      if (MB_SUCCESS != rval)
>        RETFALSE("can't skin a surface ", surface_ents[0])
>
>
> diff --git a/src/MergeMesh.cpp b/src/MergeMesh.cpp
> index 3ea7623..71119a3 100644
> --- a/src/MergeMesh.cpp
> +++ b/src/MergeMesh.cpp
> @@ -61,7 +61,7 @@ moab::ErrorCode MergeMesh::merge_entities(moab::Range &elems,
>    // get the skin of the entities
>    moab::Skinner skinner(mbImpl);
>    moab::Range skin_range;
> -  moab::ErrorCode result = skinner.find_skin(elems, 0, skin_range);
> +  moab::ErrorCode result = skinner.find_skin(0, elems, 0, skin_range);
>    if (moab::MB_SUCCESS != result) return result;
>
>    // create a tag to mark merged-to entity; reuse tree_root
> @@ -232,7 +232,7 @@ moab::ErrorCode MergeMesh::merge_higher_dimensions(moab::Range &elems)
>    for(int dim = 1; dim <3; dim++){
>      skinEnts.clear();
>      moreDeadEnts.clear();
> -    result = skinner.find_skin(elems, dim, skinEnts);
> +    result = skinner.find_skin(0, elems, dim, skinEnts);
>      //Go through each skin entity and see if it shares adjacancies with another entity
>      for(moab::Range::iterator skinIt = skinEnts.begin(); skinIt != skinEnts.end(); skinIt++){
>        adj.clear();
>
> diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
> index 1f021ff..d344037 100644
> --- a/src/ScdInterface.cpp
> +++ b/src/ScdInterface.cpp
> @@ -5,6 +5,7 @@
>  #include "StructuredElementSeq.hpp"
>  #include "VertexSequence.hpp"
>  #include "ScdVertexData.hpp"
> +#include "MBTagConventions.hpp"
>  #ifdef USE_MPI
>  #  include "moab/ParallelComm.hpp"
>  #  include "moab/TupleList.hpp"
> @@ -21,9 +22,9 @@
>  namespace moab
>  {
>
> -const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "trivial", "nopart"};
> +const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "sqijk", "trivial", "nopart"};
>
> -ScdInterface::ScdInterface(Core *imp, bool boxes)
> +ScdInterface::ScdInterface(Interface *imp, bool boxes)
>          : mbImpl(imp),
>            searchedBoxes(false),
>            boxPeriodicTag(0),
> @@ -102,11 +103,40 @@ ScdBox *ScdInterface::get_scd_box(EntityHandle eh)
>  }
>
>  ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double * const coords, unsigned int num_coords,
> -                                      ScdBox *& new_box, int * const lperiodic, ScdParData *par_data)
> +                                      ScdBox *& new_box, int * const lperiodic, ScdParData *par_data,
> +                                      bool assign_gids, int tag_shared_ents)
>  {
>      // create a rectangular structured mesh block
>    ErrorCode rval;
>
> +  int tmp_lper[3] = {0, 0, 0};
> +  if (lperiodic) std::copy(lperiodic, lperiodic+3, tmp_lper);
> +
> +#ifndef USE_MPI
> +  if (-1 == tag_shared_ents) ERRORR(MB_FAILURE, "Parallel capability requested but MOAB not compiled parallel.");
> +  if (-1 == tag_shared_verts && !assign_gids) assign_gids = true; // need to assign gids in order to tag shared verts
> +#else
> +  if (par_data && low == high && ScdParData::NOPART != par_data->partMethod) {
> +      // requesting creation of parallel mesh, so need to compute partition
> +    if (!par_data->pComm) {
> +        // this is a really boneheaded way to have to create a PC
> +      par_data->pComm = ParallelComm::get_pcomm(mbImpl, 0);
> +      if (NULL == par_data->pComm) par_data->pComm = new ParallelComm(mbImpl, MPI_COMM_WORLD);
> +    }
> +    int ldims[6];
> +    rval = compute_partition(par_data->pComm->size(), par_data->pComm->rank(), *par_data,
> +                             ldims, tmp_lper, par_data->pDims);
> +    ERRORR(rval, "Error returned from compute_partition.");
> +    low.set(ldims);
> +    high.set(ldims+3);
> +    if (par_data->pComm->get_debug_verbosity() > 0) {
> +      std::cout << "Proc " << par_data->pComm->rank() << ": " << *par_data;
> +      std::cout << "Proc " << par_data->pComm->rank() << " local dims: "
> +                << low << "-" << high << std::endl;
> +    }
> +  }
> +#endif
> +
>    HomCoord tmp_size = high - low + HomCoord(1, 1, 1, 0);
>    if ((tmp_size[1] && num_coords && (int)num_coords < tmp_size[0]) ||
>        (tmp_size[2] && num_coords && (int)num_coords < tmp_size[0]*tmp_size[1]))
> @@ -137,7 +167,8 @@ ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double
>    }
>
>      // create element sequence
> -  SequenceManager *seq_mgr = mbImpl->sequence_manager();
> +  Core *mbcore = dynamic_cast<Core*>(mbImpl);
> +  SequenceManager *seq_mgr = mbcore->sequence_manager();
>
>    EntitySequence *tmp_seq;
>    EntityHandle start_ent;
> @@ -147,7 +178,7 @@ ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double
>    if (1 >= tmp_size[2]) this_tp = MBQUAD;
>    if (1 >= tmp_size[2] && 1 >= tmp_size[1]) this_tp = MBEDGE;
>    rval = seq_mgr->create_scd_sequence(low, high, this_tp, 0, start_ent, tmp_seq,
> -                                      lperiodic);
> +                                      tmp_lper);
>    ERRORR(rval, "Trouble creating scd element sequence.");
>
>    new_box->elem_seq(tmp_seq);
> @@ -172,9 +203,51 @@ ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double
>
>    if (par_data) new_box->par_data(*par_data);
>
> +
> +  if (assign_gids) {
> +    rval = assign_global_ids(new_box);
> +    ERRORR(rval, "Trouble assigning global ids");
> +  }
> +
> +#ifdef USE_MPI
> +  if (par_data && -1 != tag_shared_ents) {
> +    rval = tag_shared_vertices(par_data->pComm, new_box);
> +  }
> +#endif
> +
>    return MB_SUCCESS;
>  }
>
> +ErrorCode ScdInterface::assign_global_ids(ScdBox *box)
> +{
> +  // Get a ptr to global id memory
> +  void* data;
> +  int count = 0;
> +  Tag gid_tag;
> +  ErrorCode rval = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag,
> +                                          MB_TAG_CREAT & MB_TAG_DENSE, &count);
> +  ERRORR(rval, "Trouble getting global id tag handle.");
> +  Range tmp_range(box->start_vertex(), box->start_vertex() + box->num_vertices());
> +  rval = mbImpl->tag_iterate(gid_tag, tmp_range.begin(), tmp_range.end(), count, data);
> +  ERRORR(rval, "Failed to get tag iterator.");
> +  assert(count == box->num_vertices());
> +  int* gid_data = (int*) data;
> +  int di = box->par_data().gDims[3] - box->par_data().gDims[0] + 1;
> +  int dj = box->par_data().gDims[4] - box->par_data().gDims[1] + 1;
> +
> +  for (int kl = box->box_dims()[2]; kl <= box->box_dims()[5]; kl++) {
> +    for (int jl = box->box_dims()[1]; jl <= box->box_dims()[4]; jl++) {
> +      for (int il = box->box_dims()[0]; il <= box->box_dims()[3]; il++) {
> +        int itmp = (!box->locally_periodic()[0] && box->par_data().gPeriodic[0] && il == box->par_data().gDims[3] ?
> +                    box->par_data().gDims[0] : il);
> +        *gid_data = (-1 != kl ? kl * di * dj : 0) + jl * di + itmp + 1;
> +        gid_data++;
> +      }
> +    }
> +  }
> +
> +  return MB_SUCCESS;
> +}
>
>  ErrorCode ScdInterface::create_scd_sequence(HomCoord low, HomCoord high, EntityType tp,
>                                              int starting_id, ScdBox *&new_box,
> @@ -186,7 +259,8 @@ ErrorCode ScdInterface::create_scd_sequence(HomCoord low, HomCoord high, EntityT
>        (tp == MBEDGE && 1 >= tmp_size[0]))
>      return MB_TYPE_OUT_OF_RANGE;
>
> -  SequenceManager *seq_mgr = mbImpl->sequence_manager();
> +  Core *mbcore = dynamic_cast<Core*>(mbImpl);
> +  SequenceManager *seq_mgr = mbcore->sequence_manager();
>
>    EntitySequence *tmp_seq;
>    EntityHandle start_ent, scd_set;
> @@ -551,32 +625,18 @@ ErrorCode ScdBox::get_adj_edge_or_face(int dim, int i, int j, int k, int dir, En
>  }
>
>  #ifndef USE_MPI
> -ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *, EntityHandle )
> +ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *, ScdBox *)
>  {
>    return MB_FAILURE;
>  #else
> -ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, EntityHandle seth)
> +ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, ScdBox *box)
>  {
> -    // first, look for box data on the set
> -  ScdBox *box = get_scd_box(seth);
> -  Range tmp_range;
> -  ErrorCode rval;
> -  if (!box) {
> -      // look for contained boxes
> -    rval = mbImpl->get_entities_by_type(seth, MBENTITYSET, tmp_range);
> -    if (MB_SUCCESS != rval) return rval;
> -    for (Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); rit++) {
> -      box = get_scd_box(*rit);
> -      if (box) break;
> -    }
> -  }
> -
> -  if (!box) return MB_FAILURE;
> +  EntityHandle seth = box->box_set();
>
>      // check the # ents in the box against the num in the set, to make sure it's only 1 box;
>      // reuse tmp_range
> -  tmp_range.clear();
> -  rval = mbImpl->get_entities_by_dimension(seth, box->box_dimension(), tmp_range);
> +  Range tmp_range;
> +  ErrorCode rval = mbImpl->get_entities_by_dimension(seth, box->box_dimension(), tmp_range);
>    if (MB_SUCCESS != rval) return rval;
>    if (box->num_elements() != (int)tmp_range.size()) return MB_FAILURE;
>
> @@ -659,15 +719,18 @@ ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, EntityHandle se
>    if (MB_SUCCESS != rval) return rval;
>
>      // create interface sets
> -  rval = pcomm->create_interface_sets(proc_nvecs, -1, -1);
> +  rval = pcomm->create_interface_sets(proc_nvecs);
>    if (MB_SUCCESS != rval) return rval;
>
> +    // add the box to the PComm's partitionSets
> +  pcomm->partition_sets().insert(box->box_set());
> +
>      // make sure buffers are allocated for communicating procs
>    for (std::vector<int>::iterator pit = procs.begin(); pit != procs.end(); pit++)
>      pcomm->get_buffers(*pit);
>
> +  if (pcomm->get_debug_verbosity() > 1) pcomm->list_entities(NULL, 1);
>
> -  shared_data.reset();
>  #ifndef NDEBUG
>    rval = pcomm->check_all_shared_handles();
>    if (MB_SUCCESS != rval) return rval;
>
> diff --git a/src/Skinner.cpp b/src/Skinner.cpp
> index 5869777..b5fd24e 100644
> --- a/src/Skinner.cpp
> +++ b/src/Skinner.cpp
> @@ -185,7 +185,7 @@ void Skinner::add_adjacency(EntityHandle entity,
>    }
>  }
>
> -ErrorCode Skinner::find_geometric_skin(Range &forward_target_entities)
> +ErrorCode Skinner::find_geometric_skin(const EntityHandle meshset, Range &forward_target_entities)
>  {
>      // attempts to find whole model skin, using geom topo sets first then
>      // normal find_skin function
> @@ -203,7 +203,7 @@ ErrorCode Skinner::find_geometric_skin(Range &forward_target_entities)
>    Range face_sets;
>    int two = 2;
>    const void *two_ptr = &two;
> -  result = thisMB->get_entities_by_type_and_tag(0, MBENTITYSET, &geom_tag, &two_ptr, 1,
> +  result = thisMB->get_entities_by_type_and_tag(meshset, MBENTITYSET, &geom_tag, &two_ptr, 1,
>                                                   face_sets);
>
>    Range::iterator it;
> @@ -240,7 +240,8 @@ ErrorCode Skinner::find_geometric_skin(Range &forward_target_entities)
>    return result;
>  }
>
> -ErrorCode Skinner::find_skin( const Range& source_entities,
> +ErrorCode Skinner::find_skin( const EntityHandle meshset,
> +                              const Range& source_entities,
>                                bool get_vertices,
>                                Range& output_handles,
>                                Range* output_reverse_handles,
> @@ -263,65 +264,13 @@ ErrorCode Skinner::find_skin( const Range& source_entities,
>        !this_core->a_entity_factory()->vert_elem_adjacencies())
>      this_core->a_entity_factory()->create_vert_elem_adjacencies();
>
> -  if (this_core && this_core->a_entity_factory()->vert_elem_adjacencies())
> -    return find_skin_vertices( source_entities,
> -                               get_vertices ? &output_handles : 0,
> -                               get_vertices ? 0 : &output_handles,
> -                               output_reverse_handles,
> -                               create_skin_elements );
> +  return find_skin_vertices( meshset,
> +                             source_entities,
> +                             get_vertices ? &output_handles : 0,
> +                             get_vertices ? 0 : &output_handles,
> +                             output_reverse_handles,
> +                             create_skin_elements );
>
> -  Range forward, reverse;
> -  Range prev;
> -  const int d = CN::Dimension(TYPE_FROM_HANDLE(source_entities.front()));
> -  if (!source_entities.all_of_dimension(d))
> -    return MB_TYPE_OUT_OF_RANGE;
> -
> -  rval = thisMB->get_entities_by_dimension( 0, d-1, prev );
> -  if (MB_SUCCESS != rval)
> -    return rval;
> -
> -  rval = find_skin_noadj( source_entities, forward, reverse );
> -  if (MB_SUCCESS != rval)
> -    return rval;
> -
> -  if (get_vertices && !output_reverse_handles) {
> -    forward.merge( reverse );
> -    reverse.clear();
> -  }
> -
> -  if (get_vertices) {
> -    rval = thisMB->get_connectivity( forward, output_handles );
> -    if (MB_SUCCESS != rval)
> -      return rval;
> -  }
> -
> -  if (!create_skin_elements) {
> -    Range new_skin;
> -    rval = thisMB->get_entities_by_dimension( 0, d-1, new_skin);
> -    if (MB_SUCCESS != rval)
> -      return rval;
> -    new_skin = subtract( new_skin, prev );
> -    forward = subtract( forward, new_skin );
> -    reverse = subtract( reverse, new_skin );
> -    rval = thisMB->delete_entities( new_skin );
> -    if (MB_SUCCESS != rval)
> -      return rval;
> -  }
> -
> -  if (!get_vertices) {
> -    if (output_handles.empty())
> -      output_handles.swap( forward );
> -    else
> -      output_handles.merge( forward );
> -    if (!output_reverse_handles)
> -      output_handles.merge( reverse );
> -    else if (output_reverse_handles->empty())
> -      output_reverse_handles->swap( reverse );
> -    else
> -      output_reverse_handles->merge( reverse );
> -  }
> -
> -  return MB_SUCCESS;
>  }
>
>  ErrorCode Skinner::find_skin_scd(const Range& source_entities,
> @@ -1062,13 +1011,14 @@ bool Skinner::has_larger_angle(EntityHandle &entity1,
>  }
>
>    // get skin entities of prescribed dimension
> -ErrorCode Skinner::find_skin(const Range &entities,
> +ErrorCode Skinner::find_skin(const EntityHandle this_set,
> +                             const Range &entities,
>                                   int dim,
>                                   Range &skin_entities,
>                                   bool create_vert_elem_adjs)
>  {
>    Range tmp_skin;
> -  ErrorCode result = find_skin(entities, (dim==0), tmp_skin, 0,
> +  ErrorCode result = find_skin(this_set, entities, (dim==0), tmp_skin, 0,
>                                   create_vert_elem_adjs, true);
>    if (MB_SUCCESS != result || tmp_skin.empty()) return result;
>
> @@ -1086,7 +1036,8 @@ ErrorCode Skinner::find_skin(const Range &entities,
>    return result;
>  }
>
> -ErrorCode Skinner::find_skin_vertices( const Range& entities,
> +ErrorCode Skinner::find_skin_vertices( const EntityHandle this_set,
> +                                       const Range& entities,
>                                             Range* skin_verts,
>                                             Range* skin_elems,
>                                             Range* skin_rev_elems,
> @@ -1104,7 +1055,7 @@ ErrorCode Skinner::find_skin_vertices( const Range& entities,
>      // are we skinning all entities
>    size_t count = entities.size();
>    int num_total;
> -  rval = thisMB->get_number_entities_by_dimension( 0, dim, num_total );
> +  rval = thisMB->get_number_entities_by_dimension( this_set, dim, num_total );
>    if (MB_SUCCESS != rval)
>      return rval;
>    bool all = (count == (size_t)num_total);
>
> diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
> index 0fca661..0ad7e19 100644
> --- a/src/io/NCHelper.cpp
> +++ b/src/io/NCHelper.cpp
> @@ -57,7 +57,7 @@ NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOptions&
>  ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums) {
>    Interface*& mbImpl = _readNC->mbImpl;
>    std::vector<std::string>& dimNames = _readNC->dimNames;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    std::map<std::string, ReadNC::AttData>& globalAtts = _readNC->globalAtts;
>    std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
>    DebugOutput& dbgOut = _readNC->dbgOut;
> @@ -94,7 +94,7 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
>    tag_name = "__DIM_NAMES";
>    std::string dimnames;
>    unsigned int dimNamesSz = dimNames.size();
> -  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> +  for (unsigned int i = 0; i != dimNamesSz; i++) {
>      dimnames.append(dimNames[i]);
>      dimnames.push_back('\0');
>    }
> @@ -107,16 +107,15 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
>    if (MB_SUCCESS == rval)
>      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>
> -  // <__DIM_VALUES>
> -  Tag dimValsTag = 0;
> -  tag_name = "__DIM_VALUES";
> -  int dimValsSz = (int)dimVals.size();
> -
> -  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_INTEGER, dimValsTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> -  ERRORR(rval, "Trouble creating __DIM_VALUES tag.");
> -  ptr = &(dimVals[0]);
> -  rval = mbImpl->tag_set_by_ptr(dimValsTag, &_fileSet, 1, &ptr, &dimValsSz);
> -  ERRORR(rval, "Trouble setting data for __DIM_VALUES tag.");
> +  // <__DIM_LENS>
> +  Tag dimLensTag = 0;
> +  tag_name = "__DIM_LENS";
> +  int dimLensSz = dimLens.size();
> +  rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> +  ERRORR(rval, "Trouble creating __DIM_LENS tag.");
> +  ptr = &(dimLens[0]);
> +  rval = mbImpl->tag_set_by_ptr(dimLensTag, &_fileSet, 1, &ptr, &dimLensSz);
> +  ERRORR(rval, "Trouble setting data for __DIM_LENS tag.");
>    if (MB_SUCCESS == rval)
>      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>
> @@ -138,8 +137,8 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
>    if (MB_SUCCESS == rval)
>      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>
> -  // __<dim_name>_LOC_MINMAX
> -  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> +  // __<dim_name>_LOC_MINMAX (for time)
> +  for (unsigned int i = 0; i != dimNamesSz; i++) {
>      if (dimNames[i] == "time") {
>        std::stringstream ss_tag_name;
>        ss_tag_name << "__" << dimNames[i] << "_LOC_MINMAX";
> @@ -157,28 +156,28 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
>      }
>    }
>
> -  // __<dim_name>_LOC_VALS
> -  for (unsigned int i = 0; i != dimNamesSz; ++i) {
> -    if (dimNames[i] != "time")
> -      continue;
> -    std::vector<int> val;
> -    if (!tstep_nums.empty())
> -      val = tstep_nums;
> -    else {
> -      val.resize(tVals.size());
> -      for (unsigned int j = 0; j != tVals.size(); ++j)
> -        val[j] = j;
> +  // __<dim_name>_LOC_VALS (for time)
> +  for (unsigned int i = 0; i != dimNamesSz; i++) {
> +    if (dimNames[i] == "time") {
> +      std::vector<int> val;
> +      if (!tstep_nums.empty())
> +        val = tstep_nums;
> +      else {
> +        val.resize(tVals.size());
> +        for (unsigned int j = 0; j != tVals.size(); j++)
> +          val[j] = j;
> +      }
> +      Tag tagh = 0;
> +      std::stringstream ss_tag_name;
> +      ss_tag_name << "__" << dimNames[i] << "_LOC_VALS";
> +      tag_name = ss_tag_name.str();
> +      rval = mbImpl->tag_get_handle(tag_name.c_str(), val.size(), MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> +      ERRORR(rval, "Trouble creating __<dim_name>_LOC_VALS tag.");
> +      rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> +      ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_VALS tag.");
> +      if (MB_SUCCESS == rval)
> +        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>      }
> -    Tag tagh = 0;
> -    std::stringstream ss_tag_name;
> -    ss_tag_name << "__" << dimNames[i] << "_LOC_VALS";
> -    tag_name = ss_tag_name.str();
> -    rval = mbImpl->tag_get_handle(tag_name.c_str(), val.size(), MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> -    ERRORR(rval, "Trouble creating __<dim_name>_LOC_VALS tag.");
> -    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> -    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_VALS tag.");
> -    if (MB_SUCCESS == rval)
> -      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>    }
>
>    // __<var_name>_DIMS
> @@ -191,7 +190,7 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
>      if (varDimSz == 0)
>        continue;
>      varInfo[mapIter->first].varTags.resize(varDimSz, 0);
> -    for (unsigned int i = 0; i != varDimSz; ++i) {
> +    for (unsigned int i = 0; i != varDimSz; i++) {
>        Tag tmptag = 0;
>        std::string tmptagname = dimNames[varInfo[mapIter->first].varDims[i]];
>        mbImpl->tag_get_handle(tmptagname.c_str(), 0, MB_TYPE_OPAQUE, tmptag, MB_TAG_ANY);
> @@ -316,7 +315,6 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
>
>    // Finally, read into that space
>    int success;
> -  std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vdatas.size() * tstep_nums.size());
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end() )
>         continue; // This is a dummy one, we don't have it; we created it for the dummy tag
> @@ -327,28 +325,28 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
>          case NC_BYTE:
>          case NC_CHAR:
>            success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              (char*) data NCREQ);
> +              (char*) data);
>            ERRORS(success, "Failed to read char data.");
>            break;
>          case NC_DOUBLE:
>            success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              (double*) data NCREQ);
> +              (double*) data);
>            ERRORS(success, "Failed to read double data.");
>            break;
>          case NC_FLOAT: {
>            success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              (float*) data NCREQ);
> +              (float*) data);
>            ERRORS(success, "Failed to read float data.");
>            break;
>          }
>          case NC_INT:
>            success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              (int*) data NCREQ);
> +              (int*) data);
>            ERRORS(success, "Failed to read int data.");
>            break;
>          case NC_SHORT:
>            success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              (short*) data NCREQ);
> +              (short*) data);
>            ERRORS(success, "Failed to read short data.");
>            break;
>          default:
> @@ -362,11 +360,6 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
>      }
>    }
>
> -#ifdef NCWAIT
> -  int success = ncmpi_wait_all(fileId, requests.size(), &requests[0], &statuss[0]);
> -  ERRORS(success, "Failed on wait_all.");
> -#endif
> -
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
> @@ -501,13 +494,13 @@ ErrorCode NCHelper::read_coordinate(const char* var_name, int lmin, int lmax, st
>
>    // Check to make sure it's a float or double
>    if (NC_DOUBLE == (*vmit).second.varDataType) {
> -    fail = NCFUNCA(get_vars_double)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &cvals[0]);
> +    fail = NCFUNCAG(_vars_double)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &cvals[0]);
>      if (fail)
>        ERRORS(MB_FAILURE, "Failed to get coordinate values.");
>    }
>    else if (NC_FLOAT == (*vmit).second.varDataType) {
>      std::vector<float> tcvals(tcount);
> -    fail = NCFUNCA(get_vars_float)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &tcvals[0]);
> +    fail = NCFUNCAG(_vars_float)(_fileId, (*vmit).second.varId, &tstart, &tcount, &dum_stride, &tcvals[0]);
>      if (fail)
>        ERRORS(MB_FAILURE, "Failed to get coordinate values.");
>      std::copy(tcvals.begin(), tcvals.end(), cvals.begin());
> @@ -693,7 +686,7 @@ void NCHelper::init_dims_with_no_cvars_info()
>
>  ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = MB_SUCCESS;
> @@ -712,7 +705,7 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
>        }
>
>        // Assume point-based values for now?
> -      if (-1 == tDim || dimVals[tDim] <= (int) t)
> +      if (-1 == tDim || dimLens[tDim] <= (int) t)
>          ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
>
>        // Set up the dimensions and counts
> @@ -742,7 +735,7 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
>            if (tDim != vdatas[i].varDims[idx]){
>              // Push other variable dimensions, except time, which was already pushed
>              vdatas[i].readStarts[t].push_back(0);
> -            vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[idx]]);
> +            vdatas[i].readCounts[t].push_back(dimLens[vdatas[i].varDims[idx]]);
>            }
>          }
>        }
> @@ -819,6 +812,7 @@ ErrorCode ScdNCHelper::create_mesh(Range& faces)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
>    Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>    ScdInterface* scdi = _readNC->scdi;
>    ScdParData& parData = _readNC->parData;
> @@ -826,12 +820,29 @@ ErrorCode ScdNCHelper::create_mesh(Range& faces)
>    Range tmp_range;
>    ScdBox *scd_box;
>
> -  ErrorCode rval = scdi->construct_box(HomCoord(lDims[0], lDims[1], lDims[2], 1), HomCoord(lDims[3], lDims[4], lDims[5], 1), NULL,
> -      0, scd_box, locallyPeriodic, &parData);
> +  ErrorCode rval = scdi->construct_box(HomCoord(lDims[0], lDims[1], lDims[2], 1), HomCoord(lDims[3], lDims[4], lDims[5], 1),
> +                                       NULL, 0, scd_box, locallyPeriodic, &parData, true);
>    ERRORR(rval, "Trouble creating scd vertex sequence.");
>
> -  // Add box set and new vertices, elements to the file set
> +    // add verts to tmp_range first, so we can duplicate global ids in vertex ids
>    tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1);
> +
> +  if (mpFileIdTag) {
> +    Range::iterator topv = tmp_range.end();
> +    int count;
> +    void *data;
> +    rval = mbImpl->tag_iterate(*mpFileIdTag, tmp_range.begin(), topv, count, data);
> +    ERRORR(rval, "Failed to get tag iterator on file id tag.");
> +    assert(count == scd_box->num_vertices());
> +    int *fid_data = (int*) data;
> +    rval = mbImpl->tag_iterate(mGlobalIdTag, tmp_range.begin(), topv, count, data);
> +    ERRORR(rval, "Failed to get tag iterator on file id tag.");
> +    assert(count == scd_box->num_vertices());
> +    int *gid_data = (int*) data;
> +    for (int i = 0; i < count; i++) fid_data[i] = gid_data[i];
> +  }
> +
> +    // Then add box set and elements to the range, then to the file set
>    tmp_range.insert(scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1);
>    tmp_range.insert(scd_box->box_set());
>    rval = mbImpl->add_entities(_fileSet, tmp_range);
> @@ -839,26 +850,14 @@ ErrorCode ScdNCHelper::create_mesh(Range& faces)
>
>    dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_elements(), scd_box->num_vertices());
>
> -  // Get a ptr to global id memory
> -  void* data;
> -  int count;
> -  const Range::iterator topv = tmp_range.upper_bound(tmp_range.begin(), tmp_range.end(), scd_box->start_vertex()
> -      + scd_box->num_vertices());
> -  rval = mbImpl->tag_iterate(mGlobalIdTag, tmp_range.begin(), topv, count, data);
> -  ERRORR(rval, "Failed to get tag iterator.");
> -  assert(count == scd_box->num_vertices());
> -  int* gid_data = (int*) data;
> -
>    // Set the vertex coordinates
>    double *xc, *yc, *zc;
>    rval = scd_box->get_coordinate_arrays(xc, yc, zc);
>    ERRORR(rval, "Couldn't get vertex coordinate arrays.");
>
> -  int i, j, k, il, jl, kl, itmp;
> +  int i, j, k, il, jl, kl;
>    int dil = lDims[3] - lDims[0] + 1;
>    int djl = lDims[4] - lDims[1] + 1;
> -  int di = gDims[3] - gDims[0] + 1;
> -  int dj = gDims[4] - gDims[1] + 1;
>    assert(dil == (int)ilVals.size() && djl == (int)jlVals.size() &&
>        (-1 == lDims[2] || lDims[5]-lDims[2] + 1 == (int)levVals.size()));
>  #define INDEX(i, j, k) ()
> @@ -872,9 +871,6 @@ ErrorCode ScdNCHelper::create_mesh(Range& faces)
>          xc[pos] = ilVals[i];
>          yc[pos] = jlVals[j];
>          zc[pos] = (-1 == lDims[2] ? 0.0 : levVals[k]);
> -        itmp = (!locallyPeriodic[0] && globallyPeriodic[0] && il == gDims[3] ? gDims[0] : il);
> -        *gid_data = (-1 != kl ? kl * di * dj : 0) + jl * di + itmp + 1;
> -        gid_data++;
>        }
>      }
>    }
> @@ -1017,7 +1013,7 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
>  ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = MB_SUCCESS;
> @@ -1067,7 +1063,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
>        }
>
>        // Assume point-based values for now?
> -      if (-1 == tDim || dimVals[tDim] <= (int) t) {
> +      if (-1 == tDim || dimLens[tDim] <= (int) t) {
>          ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
>        }
>        else if (vdatas[i].varDims[0] != tDim) {
> @@ -1152,7 +1148,6 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>
>    // Finally, read into that space
>    int success;
> -  std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vdatas.size() * tstep_nums.size());
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      std::size_t sz = vdatas[i].sz;
>
> @@ -1167,7 +1162,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>          case NC_CHAR: {
>            std::vector<char> tmpchardata(sz);
>            success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              &tmpchardata[0] NCREQ);
> +              &tmpchardata[0]);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
>              success = kji_to_jik(ni, nj, nk, data, &tmpchardata[0]);
> @@ -1181,7 +1176,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>          case NC_DOUBLE: {
>            std::vector<double> tmpdoubledata(sz);
>            success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              &tmpdoubledata[0] NCREQ);
> +              &tmpdoubledata[0]);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
>              success = kji_to_jik(ni, nj, nk, data, &tmpdoubledata[0]);
> @@ -1195,7 +1190,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>          case NC_FLOAT: {
>            std::vector<float> tmpfloatdata(sz);
>            success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              &tmpfloatdata[0] NCREQ);
> +              &tmpfloatdata[0]);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
>              success = kji_to_jik(ni, nj, nk, data, &tmpfloatdata[0]);
> @@ -1209,7 +1204,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>          case NC_INT: {
>            std::vector<int> tmpintdata(sz);
>            success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              &tmpintdata[0] NCREQ);
> +              &tmpintdata[0]);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
>              success = kji_to_jik(ni, nj, nk, data, &tmpintdata[0]);
> @@ -1223,7 +1218,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>          case NC_SHORT: {
>            std::vector<short> tmpshortdata(sz);
>            success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
> -              &tmpshortdata[0] NCREQ);
> +              &tmpshortdata[0]);
>            if (vdatas[i].numLev != 1)
>              // Switch from k varying slowest to k varying fastest
>              success = kji_to_jik(ni, nj, nk, data, &tmpshortdata[0]);
> @@ -1243,11 +1238,6 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
>      }
>    }
>
> -#ifdef NCWAIT
> -  int success = ncmpi_wait_all(fileId, requests.size(), &requests[0], &statuss[0]);
> -  ERRORS(success, "Failed on wait_all.");
> -#endif
> -
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
>
> diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
> index 7c80dc7..e5b3f08 100644
> --- a/src/io/NCHelperEuler.cpp
> +++ b/src/io/NCHelperEuler.cpp
> @@ -53,7 +53,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
>    std::vector<std::string>& dimNames = _readNC->dimNames;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>    bool& isParallel = _readNC->isParallel;
> @@ -71,7 +71,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>    }
>    iCDim = idx;
>    gCDims[0] = 0;
> -  gCDims[3] = dimVals[idx] - 1;
> +  gCDims[3] = dimLens[idx] - 1;
>
>    // Check i periodicity and set globallyPeriodic[0]
>    std::vector<double> til_vals(2);
> @@ -92,7 +92,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>    }
>    jCDim = idx;
>    gCDims[1] = 0;
> -  gCDims[4] = dimVals[idx] - 1;
> +  gCDims[4] = dimLens[idx] - 1;
>
>    // For Eul models, will always be non-periodic in j
>    gDims[1] = 0;
> @@ -111,7 +111,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'time' or 't' dimension.");
>    }
>    tDim = idx;
> -  nTimeSteps = dimVals[idx];
> +  nTimeSteps = dimLens[idx];
>
>    // Look for level dimension
>    if ((vit = std::find(dimNames.begin(), dimNames.end(), "lev")) != dimNames.end())
> @@ -122,7 +122,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension.");
>    }
>    levDim = idx;
> -  nLevels = dimVals[idx];
> +  nLevels = dimLens[idx];
>
>    // Parse options to get subset
>    int rank = 0, procs = 1;
> @@ -328,35 +328,49 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>        vd.entLoc = ReadNC::ENTLOCFACE;
>    }
>
> -  // <coordinate_dim_name>
> -  std::vector<std::string> ijdimNames(4);
> -  ijdimNames[0] = "__slon";
> -  ijdimNames[1] = "__slat";
> -  ijdimNames[2] = "__lon";
> -  ijdimNames[3] = "__lat";
> +  std::vector<std::string> ijdimNames(2);
> +  ijdimNames[0] = "__lon";
> +  ijdimNames[1] = "__lat";
>
> +  std::stringstream ss_tag_name;
>    std::string tag_name;
> -  int val_len = 0;
> +  Tag tagh;
> +
> +  // __<dim_name>_LOC_MINMAX (for lon and lat)
>    for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    tag_name = ijdimNames[i];
> -    void* val = NULL;
> -    if (tag_name == "__slon") {
> -      val = &ilVals[0];
> -      val_len = ilVals.size();
> +    std::vector<int> val(2, 0);
> +    if (ijdimNames[i] == "__lon") {
> +      val[0] = lCDims[0];
> +      val[1] = lCDims[3];
>      }
> -    else if (tag_name == "__slat") {
> -      val = &jlVals[0];
> -      val_len = jlVals.size();
> +    else if (ijdimNames[i] == "__lat") {
> +      val[0] = lCDims[1];
> +      val[1] = lCDims[4];
>      }
> -    else if (tag_name == "__lon") {
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
> +    tag_name = ss_tag_name.str();
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> +    ERRORR(rval, "Trouble creating __<dim_name>_LOC_MINMAX tag.");
> +    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_MINMAX tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +  }
> +
> +  // __<dim_name>_LOC_VALS (for lon and lat)
> +  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> +    void* val = NULL;
> +    int val_len = 0;
> +    if (ijdimNames[i] == "__lon") {
>        val = &ilCVals[0];
>        val_len = ilCVals.size();
>      }
> -    else if (tag_name == "__lat") {
> +    else if (ijdimNames[i] == "__lat") {
>        val = &jlCVals[0];
>        val_len = jlCVals.size();
>      }
> -    Tag tagh = 0;
> +
>      DataType data_type;
>
>      // Assume all has same data type as lon
> @@ -378,61 +392,21 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>          ERRORR(MB_FAILURE, "Unrecognized data type");
>          break;
>      }
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_LOC_VALS";
> +    tag_name = ss_tag_name.str();
>      rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, data_type, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> -    ERRORR(rval, "Trouble creating <coordinate_dim_name> tag.");
> +    ERRORR(rval, "Trouble creating __<dim_name>_LOC_VALS tag.");
>      rval = mbImpl->tag_set_by_ptr(tagh, &_fileSet, 1, &val, &val_len);
> -    ERRORR(rval, "Trouble setting data for <coordinate_dim_name> tag.");
> -    if (MB_SUCCESS == rval)
> -      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> -  }
> -
> -  // __<coordinate_dim_name>_LOC_MINMAX
> -  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    std::stringstream ss_tag_name;
> -    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
> -    tag_name = ss_tag_name.str();
> -    Tag tagh = 0;
> -    std::vector<int> val(2, 0);
> -    if (ijdimNames[i] == "__slon") {
> -      val[0] = lDims[0];
> -      val[1] = lDims[3];
> -    }
> -    else if (ijdimNames[i] == "__slat") {
> -      val[0] = lDims[1];
> -      val[1] = lDims[4];
> -    }
> -    else if (ijdimNames[i] == "__lon") {
> -      val[0] = lCDims[0];
> -      val[1] = lCDims[3];
> -    }
> -    else if (ijdimNames[i] == "__lat") {
> -      val[0] = lCDims[1];
> -      val[1] = lCDims[4];
> -    }
> -    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> -    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_LOC_MINMAX tag.");
> -    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> -    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_LOC_MINMAX tag.");
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_VALS tag.");
>      if (MB_SUCCESS == rval)
>        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>    }
>
> -  // __<coordinate_dim_name>_GLOBAL_MINMAX
> +  // __<dim_name>_GLOBAL_MINMAX (for lon and lat)
>    for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    std::stringstream ss_tag_name;
> -    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
> -    tag_name = ss_tag_name.str();
> -    Tag tagh = 0;
>      std::vector<int> val(2, 0);
> -    if (ijdimNames[i] == "__slon") {
> -      val[0] = gDims[0];
> -      val[1] = gDims[3];
> -    }
> -    else if (ijdimNames[i] == "__slat") {
> -      val[0] = gDims[1];
> -      val[1] = gDims[4];
> -    }
> -    else if (ijdimNames[i] == "__lon") {
> +    if (ijdimNames[i] == "__lon") {
>        val[0] = gCDims[0];
>        val[1] = gCDims[3];
>      }
> @@ -440,10 +414,13 @@ ErrorCode NCHelperEuler::init_mesh_vals()
>        val[0] = gCDims[1];
>        val[1] = gCDims[4];
>      }
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
> +    tag_name = ss_tag_name.str();
>      rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> -    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
> +    ERRORR(rval, "Trouble creating __<dim_name>_GLOBAL_MINMAX tag.");
>      rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> -    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_GLOBAL_MINMAX tag.");
>      if (MB_SUCCESS == rval)
>        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>    }
>
> diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
> index 8b21e36..dd555ff 100644
> --- a/src/io/NCHelperFV.cpp
> +++ b/src/io/NCHelperFV.cpp
> @@ -46,7 +46,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
>    std::vector<std::string>& dimNames = _readNC->dimNames;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>    bool& isParallel = _readNC->isParallel;
> @@ -64,7 +64,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>    }
>    iDim = idx;
>    gDims[0] = 0;
> -  gDims[3] = dimVals[idx] - 1;
> +  gDims[3] = dimLens[idx] - 1;
>
>    // Then j
>    if ((vit = std::find(dimNames.begin(), dimNames.end(), "slat")) != dimNames.end())
> @@ -74,7 +74,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>    }
>    jDim = idx;
>    gDims[1] = 0;
> -  gDims[4] = dimVals[idx] - 1 + 2; // Add 2 for the pole points
> +  gDims[4] = dimLens[idx] - 1 + 2; // Add 2 for the pole points
>
>    // Look for names of center i/j dimensions
>    // First i
> @@ -85,7 +85,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>    }
>    iCDim = idx;
>    gCDims[0] = 0;
> -  gCDims[3] = dimVals[idx] - 1;
> +  gCDims[3] = dimLens[idx] - 1;
>
>    // Check i periodicity and set globallyPeriodic[0]
>    std::vector<double> til_vals(2);
> @@ -106,7 +106,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>    }
>    jCDim = idx;
>    gCDims[1] = 0;
> -  gCDims[4] = dimVals[idx] - 1;
> +  gCDims[4] = dimLens[idx] - 1;
>
>    // For FV models, will always be non-periodic in j
>    assert(gDims[4] == gCDims[4] + 1);
> @@ -124,7 +124,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'time' or 't' dimension.");
>    }
>    tDim = idx;
> -  nTimeSteps = dimVals[idx];
> +  nTimeSteps = dimLens[idx];
>
>    // Get number of levels
>    if ((vit = std::find(dimNames.begin(), dimNames.end(), "lev")) != dimNames.end())
> @@ -135,7 +135,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension.");
>    }
>    levDim = idx;
> -  nLevels = dimVals[idx];
> +  nLevels = dimLens[idx];
>
>    // Parse options to get subset
>    int rank = 0, procs = 1;
> @@ -330,35 +330,67 @@ ErrorCode NCHelperFV::init_mesh_vals()
>        vd.entLoc = ReadNC::ENTLOCEWEDGE;
>    }
>
> -  // <coordinate_dim_name>
>    std::vector<std::string> ijdimNames(4);
>    ijdimNames[0] = "__slon";
>    ijdimNames[1] = "__slat";
>    ijdimNames[2] = "__lon";
>    ijdimNames[3] = "__lat";
>
> +  std::stringstream ss_tag_name;
>    std::string tag_name;
> -  int val_len = 0;
> +  Tag tagh;
> +
> +  // __<dim_name>_LOC_MINMAX (for slon, slat, lon and lat)
> +  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> +    std::vector<int> val(2, 0);
> +    if (ijdimNames[i] == "__slon") {
> +      val[0] = lDims[0];
> +      val[1] = lDims[3];
> +    }
> +    else if (ijdimNames[i] == "__slat") {
> +      val[0] = lDims[1];
> +      val[1] = lDims[4];
> +    }
> +    else if (ijdimNames[i] == "__lon") {
> +      val[0] = lCDims[0];
> +      val[1] = lCDims[3];
> +    }
> +    else if (ijdimNames[i] == "__lat") {
> +      val[0] = lCDims[1];
> +      val[1] = lCDims[4];
> +    }
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
> +    tag_name = ss_tag_name.str();
> +    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> +    ERRORR(rval, "Trouble creating __<dim_name>_LOC_MINMAX tag.");
> +    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_MINMAX tag.");
> +    if (MB_SUCCESS == rval)
> +      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> +  }
> +
> +  // __<dim_name>_LOC_VALS (for slon, slat, lon and lat)
>    for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    tag_name = ijdimNames[i];
>      void* val = NULL;
> -    if (tag_name == "__slon") {
> +    int val_len = 0;
> +    if (ijdimNames[i] == "__slon") {
>        val = &ilVals[0];
>        val_len = ilVals.size();
>      }
> -    else if (tag_name == "__slat") {
> +    else if (ijdimNames[i] == "__slat") {
>        val = &jlVals[0];
>        val_len = jlVals.size();
>      }
> -    else if (tag_name == "__lon") {
> +    else if (ijdimNames[i] == "__lon") {
>        val = &ilCVals[0];
>        val_len = ilCVals.size();
>      }
> -    else if (tag_name == "__lat") {
> +    else if (ijdimNames[i] == "__lat") {
>        val = &jlCVals[0];
>        val_len = jlCVals.size();
>      }
> -    Tag tagh = 0;
> +
>      DataType data_type;
>
>      // Assume all has same data type as lon
> @@ -380,51 +412,19 @@ ErrorCode NCHelperFV::init_mesh_vals()
>          ERRORR(MB_FAILURE, "Unrecognized data type");
>          break;
>      }
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_LOC_VALS";
> +    tag_name = ss_tag_name.str();
>      rval = mbImpl->tag_get_handle(tag_name.c_str(), 0, data_type, tagh, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
> -    ERRORR(rval, "Trouble creating <coordinate_dim_name> tag.");
> +    ERRORR(rval, "Trouble creating __<dim_name>_LOC_VALS tag.");
>      rval = mbImpl->tag_set_by_ptr(tagh, &_fileSet, 1, &val, &val_len);
> -    ERRORR(rval, "Trouble setting data for <coordinate_dim_name> tag.");
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_LOC_VALS tag.");
>      if (MB_SUCCESS == rval)
>        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>    }
>
> -  // __<coordinate_dim_name>_LOC_MINMAX
> +  // __<dim_name>_GLOBAL_MINMAX (for slon, slat, lon and lat)
>    for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    std::stringstream ss_tag_name;
> -    ss_tag_name << ijdimNames[i] << "_LOC_MINMAX";
> -    tag_name = ss_tag_name.str();
> -    Tag tagh = 0;
> -    std::vector<int> val(2, 0);
> -    if (ijdimNames[i] == "__slon") {
> -      val[0] = lDims[0];
> -      val[1] = lDims[3];
> -    }
> -    else if (ijdimNames[i] == "__slat") {
> -      val[0] = lDims[1];
> -      val[1] = lDims[4];
> -    }
> -    else if (ijdimNames[i] == "__lon") {
> -      val[0] = lCDims[0];
> -      val[1] = lCDims[3];
> -    }
> -    else if (ijdimNames[i] == "__lat") {
> -      val[0] = lCDims[1];
> -      val[1] = lCDims[4];
> -    }
> -    rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> -    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_LOC_MINMAX tag.");
> -    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> -    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_LOC_MINMAX tag.");
> -    if (MB_SUCCESS == rval)
> -      dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
> -  }
> -
> -  // __<coordinate_dim_name>_GLOBAL_MINMAX
> -  for (unsigned int i = 0; i != ijdimNames.size(); i++) {
> -    std::stringstream ss_tag_name;
> -    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
> -    tag_name = ss_tag_name.str();
> -    Tag tagh = 0;
>      std::vector<int> val(2, 0);
>      if (ijdimNames[i] == "__slon") {
>        val[0] = gDims[0];
> @@ -442,10 +442,13 @@ ErrorCode NCHelperFV::init_mesh_vals()
>        val[0] = gCDims[1];
>        val[1] = gCDims[4];
>      }
> +    ss_tag_name.clear();
> +    ss_tag_name << ijdimNames[i] << "_GLOBAL_MINMAX";
> +    tag_name = ss_tag_name.str();
>      rval = mbImpl->tag_get_handle(tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT);
> -    ERRORR(rval, "Trouble creating __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
> +    ERRORR(rval, "Trouble creating __<dim_name>_GLOBAL_MINMAX tag.");
>      rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &val[0]);
> -    ERRORR(rval, "Trouble setting data for __<coordinate_dim_name>_GLOBAL_MINMAX tag.");
> +    ERRORR(rval, "Trouble setting data for __<dim_name>_GLOBAL_MINMAX tag.");
>      if (MB_SUCCESS == rval)
>        dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
>    }
>
> diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
> index d6138b2..f883bd7 100644
> --- a/src/io/NCHelperHOMME.cpp
> +++ b/src/io/NCHelperHOMME.cpp
> @@ -25,9 +25,6 @@ _spectralOrder(-1), connectId(-1)
>        readNC->readMeshIface->report_error("%s", "Failed to read np global attribute int data.");
>      else
>        _spectralOrder--; // Spectral order is one less than np
> -
> -    if (MB_SUCCESS == opts.match_option("PARTITION_METHOD", "NODAL_PARTITION"))
> -      readNC->partMethod = -1;
>    }
>  }
>
> @@ -62,7 +59,7 @@ bool NCHelperHOMME::can_read_file(ReadNC* readNC, int fileId)
>  ErrorCode NCHelperHOMME::init_mesh_vals()
>  {
>    std::vector<std::string>& dimNames = _readNC->dimNames;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
>
>    ErrorCode rval;
> @@ -78,7 +75,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'time' or 't' dimension.");
>    }
>    tDim = idx;
> -  nTimeSteps = dimVals[idx];
> +  nTimeSteps = dimLens[idx];
>
>    // Get number of vertices (labeled as number of columns)
>    if ((vit = std::find(dimNames.begin(), dimNames.end(), "ncol")) != dimNames.end())
> @@ -87,7 +84,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'ncol' dimension.");
>    }
>    vDim = idx;
> -  nVertices = dimVals[idx];
> +  nVertices = dimLens[idx];
>
>    // Set number of cells
>    nCells = nVertices - 2;
> @@ -101,7 +98,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
>      ERRORR(MB_FAILURE, "Couldn't find 'lev' or 'ilev' dimension.");
>    }
>    levDim = idx;
> -  nLevels = dimVals[idx];
> +  nLevels = dimLens[idx];
>
>    // Store lon values in xVertVals
>    std::map<std::string, ReadNC::VarData>::iterator vmit;
> @@ -131,7 +128,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
>      char posval[10];
>      int success = NCFUNC(get_att_text)(_fileId, (*vmit).second.varId, "positive", posval);
>      if (0 == success && !strcmp(posval, "down")) {
> -      for (std::vector<double>::iterator dvit = zVertVals.begin(); dvit != zVertVals.end(); ++dvit)
> +      for (std::vector<double>::iterator dvit = levVals.begin(); dvit != levVals.end(); ++dvit)
>          (*dvit) *= -1.0;
>      }
>    }
> @@ -203,6 +200,7 @@ ErrorCode NCHelperHOMME::check_existing_mesh()
>
>        // Restore localGidVerts
>        std::copy(gids.rbegin(), gids.rend(), range_inserter(localGidVerts));
> +      nLocalVertices = localGidVerts.size();
>      }
>    }
>
> @@ -236,7 +234,8 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>
>    int success;
>
> -  int rank = 0, procs = 1;
> +  int rank = 0;
> +  int procs = 1;
>  #ifdef USE_MPI
>    bool& isParallel = _readNC->isParallel;
>    if (isParallel) {
> @@ -277,18 +276,19 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>      ERRORR(MB_FAILURE, "Failed to get number of quads.");
>    }
>    int num_quads = conn_vals[idx];
> -  if (num_quads != nVertices - 2) {
> -    dbgOut.tprintf(1, "Warning: number of quads from %s and vertices from %s are inconsistent; nverts = %d, nquads = %d.\n",
> -        conn_fname.c_str(), fileName.c_str(), nVertices, num_quads);
> +  if (num_quads != nCells) {
> +    dbgOut.tprintf(1, "Warning: number of quads from %s and cells from %s are inconsistent; num_quads = %d, nCells = %d.\n",
> +        conn_fname.c_str(), fileName.c_str(), num_quads, nCells);
>    }
>
>    // Get the connectivity into tmp_conn2 and permute into tmp_conn
>    int cornerVarId;
>    success = NCFUNC(inq_varid)(connectId, "element_corners", &cornerVarId);
>    ERRORS(success, "Failed to get variable id.");
> -  NCDF_SIZE tmp_starts[2] = {0, 0}, tmp_counts[2] = {4, static_cast<size_t>(num_quads)};
> +  NCDF_SIZE tmp_starts[2] = {0, 0};
> +  NCDF_SIZE tmp_counts[2] = {4, static_cast<NCDF_SIZE>(num_quads)};
>    std::vector<int> tmp_conn(4 * num_quads), tmp_conn2(4 * num_quads);
> -  success = NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_starts, tmp_counts, &tmp_conn2[0] NCREQ);
> +  success = NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_starts, tmp_counts, &tmp_conn2[0]);
>    ERRORS(success, "Failed to get temporary connectivity.");
>    success = NCFUNC(close)(connectId);
>    ERRORS(success, "Failed on close.");
> @@ -333,7 +333,7 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>    if (!spectralMesh) {
>      rval = _readNC->readMeshIface->get_element_connect(num_coarse_quads, 4,
>                                                MBQUAD, 0, start_quad, conn_arr,
> -                                                // might have to create gather mesh later
> +                                              // Might have to create gather mesh later
>                                                (create_gathers ? num_coarse_quads + num_quads : num_coarse_quads));
>      ERRORR(rval, "Failed to create quads.");
>      tmp_range.insert(start_quad, start_quad + num_coarse_quads - 1);
> @@ -351,21 +351,21 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>      ERRORR(rval, "Failed to get fine connectivity of spectral elements.");
>    }
>
> -  unsigned int num_local_verts = localGidVerts.size();
> -  unsigned int num_total_verts = nVertices;
> -
>    // Create vertices
> +  nLocalVertices = localGidVerts.size();
>    std::vector<double*> arrays;
> -  rval = _readNC->readMeshIface->get_node_coords(3, num_local_verts, 0, start_vertex, arrays,
> -                                          // might have to create gather mesh later
> -                                        (create_gathers ? num_local_verts + num_total_verts : num_local_verts));
> -  ERRORR(rval, "Couldn't create vertices in ucd mesh.");
> +  rval = _readNC->readMeshIface->get_node_coords(3, nLocalVertices, 0, start_vertex, arrays,
> +                                        // Might have to create gather mesh later
> +                                        (create_gathers ? nLocalVertices + nVertices : nLocalVertices));
> +  ERRORR(rval, "Couldn't create vertices in HOMME mesh.");
>
>    // Set vertex coordinates
>    Range::iterator rit;
> -  double *xptr = arrays[0], *yptr = arrays[1], *zptr = arrays[2];
> +  double* xptr = arrays[0];
> +  double* yptr = arrays[1];
> +  double* zptr = arrays[2];
>    int i;
> -  for (i = 0, rit = localGidVerts.begin(); i < (int)num_local_verts; i++, ++rit) {
> +  for (i = 0, rit = localGidVerts.begin(); i < nLocalVertices; i++, ++rit) {
>      assert(*rit < xVertVals.size() + 1);
>      xptr[i] = xVertVals[(*rit) - 1]; // lon
>      yptr[i] = yVertVals[(*rit) - 1]; // lat
> @@ -373,7 +373,7 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>
>    // Convert lon/lat/rad to x/y/z
>    const double pideg = acos(-1.0) / 180.0;
> -  for (i = 0; i < (int)num_local_verts; i++) {
> +  for (i = 0; i < nLocalVertices; i++) {
>      double cosphi = cos(pideg * yptr[i]);
>      double zmult = sin(pideg * yptr[i]);
>      double xmult = cosphi * cos(xptr[i] * pideg);
> @@ -385,12 +385,12 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>    }
>
>    // Get ptr to gid memory for vertices
> -  Range vert_range(start_vertex, start_vertex + num_local_verts - 1);
> +  Range vert_range(start_vertex, start_vertex + nLocalVertices - 1);
>    void* data;
>    int count;
>    rval = mbImpl->tag_iterate(mGlobalIdTag, vert_range.begin(), vert_range.end(), count, data);
>    ERRORR(rval, "Failed to get tag iterator.");
> -  assert(count == (int) num_local_verts);
> +  assert(count == nLocalVertices);
>    int* gid_data = (int*) data;
>    std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
>
> @@ -398,16 +398,15 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>    if (mpFileIdTag) {
>      rval = mbImpl->tag_iterate(*mpFileIdTag, vert_range.begin(), vert_range.end(), count, data);
>      ERRORR(rval, "Failed to get tag iterator on file id tag.");
> -    assert(count == (int) num_local_verts);
> +    assert(count == nLocalVertices);
>      gid_data = (int*) data;
>      std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
>    }
>
>    // Create map from file ids to vertex handles, used later to set connectivity
>    std::map<EntityHandle, EntityHandle> vert_handles;
> -  for (rit = localGidVerts.begin(), i = 0; rit != localGidVerts.end(); ++rit, i++) {
> +  for (rit = localGidVerts.begin(), i = 0; rit != localGidVerts.end(); ++rit, i++)
>      vert_handles[*rit] = start_vertex + i;
> -  }
>
>    // Compute proper handles in connectivity using offset
>    for (int q = 0; q < 4 * num_coarse_quads; q++) {
> @@ -424,9 +423,9 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>
>    // Add new vertices and elements to the set
>    faces.merge(tmp_range);
> -  tmp_range.insert(start_vertex, start_vertex + num_local_verts - 1);
> +  tmp_range.insert(start_vertex, start_vertex + nLocalVertices - 1);
>    rval = mbImpl->add_entities(_fileSet, tmp_range);
> -  ERRORR(rval, "Couldn't add new vertices and quads/hexes to file set.");
> +  ERRORR(rval, "Couldn't add new vertices and quads to file set.");
>
>    // Mark the set with the spectral order
>    Tag sporder;
> @@ -443,11 +442,13 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>      // Create vertices
>      arrays.clear();
>      // Don't need to specify allocation number here, because we know enough verts were created before
> -    rval = _readNC->readMeshIface->get_node_coords(3, num_total_verts, 0, start_vertex, arrays);
> -    ERRORR(rval, "Couldn't create vertices in ucd mesh for gather set.");
> +    rval = _readNC->readMeshIface->get_node_coords(3, nVertices, 0, start_vertex, arrays);
> +    ERRORR(rval, "Couldn't create vertices in HOMME mesh for gather set.");
>
> -    xptr = arrays[0], yptr = arrays[1], zptr = arrays[2];
> -    for (i = 0; i < (int)num_total_verts; i++) {
> +    xptr = arrays[0];
> +    yptr = arrays[1];
> +    zptr = arrays[2];
> +    for (i = 0; i < nVertices; i++) {
>        double cosphi = cos(pideg * yVertVals[i]);
>        double zmult = sin(pideg * yVertVals[i]);
>        double xmult = cosphi * cos(xVertVals[i] * pideg);
> @@ -459,21 +460,21 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>      }
>
>      // Get ptr to gid memory for vertices
> -    Range gather_verts(start_vertex, start_vertex + num_total_verts - 1);
> +    Range gather_verts(start_vertex, start_vertex + nVertices - 1);
>      rval = mbImpl->tag_iterate(mGlobalIdTag, gather_verts.begin(), gather_verts.end(), count, data);
>      ERRORR(rval, "Failed to get tag iterator.");
> -    assert(count == (int) num_total_verts);
> +    assert(count == nVertices);
>      gid_data = (int*) data;
> -    for (int j = 1; j <= (int) num_total_verts; j++)
> +    for (int j = 1; j <= nVertices; j++)
>        gid_data[j - 1] = j;
>      // Set the file id tag too, it should be bigger something not interfering with global id
>      if (mpFileIdTag) {
>        rval = mbImpl->tag_iterate(*mpFileIdTag, gather_verts.begin(), gather_verts.end(), count, data);
>        ERRORR(rval, "Failed to get tag iterator in file id tag.");
> -      assert(count == (int) num_total_verts);
> +      assert(count == nVertices);
>        gid_data = (int*) data;
> -      for (int j = 1; j <= (int) num_total_verts; j++)
> -        gid_data[j - 1] = num_total_verts + j; // bigger than global id tag
> +      for (int j = 1; j <= nVertices; j++)
> +        gid_data[j - 1] = nVertices + j; // bigger than global id tag
>      }
>
>      rval = mbImpl->add_entities(gather_set, gather_verts);
> @@ -488,7 +489,7 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
>      gather_quads.insert(start_quad, start_quad + num_quads - 1);
>      std::copy(&tmp_conn[0], &tmp_conn[4 * num_quads], conn_arr);
>      for (i = 0; i != 4 * num_quads; i++)
> -      conn_arr[i] += start_vertex - 1; // connectivity array is shifted by where the gather verts start
> +      conn_arr[i] += start_vertex - 1; // Connectivity array is shifted by where the gather verts start
>      rval = mbImpl->add_entities(gather_set, gather_quads);
>      ERRORR(rval, "Couldn't add quads to gather set.");
>    }
> @@ -568,7 +569,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>& var_n
>  ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  std::vector<int>& dimVals = _readNC->dimVals;
> +  std::vector<int>& dimLens = _readNC->dimLens;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = MB_SUCCESS;
> @@ -594,7 +595,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC
>        }
>
>        // Assume point-based values for now?
> -      if (-1 == tDim || dimVals[tDim] <= (int) t) {
> +      if (-1 == tDim || dimLens[tDim] <= (int) t) {
>          ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
>        }
>        else if (vdatas[i].varDims[0] != tDim) {
> @@ -619,7 +620,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC
>            // We will start from the first localGidVerts, actually; we will reset that
>            // later on, anyway, in a loop
>            vdatas[i].readStarts[t].push_back(localGidVerts[0] - 1);
> -          vdatas[i].readCounts[t].push_back(localGidVerts.size());
> +          vdatas[i].readCounts[t].push_back(nLocalVertices);
>            assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
>            range = &verts;
>            break;
> @@ -703,9 +704,9 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
>
>              // Do a partial read, in each subrange
>              // wait outside this loop
> -            success = NCFUNCAG2(_vara_double)(_fileId, vdatas[i].varId,
> +            success = NCFUNCREQG(_vara_double)(_fileId, vdatas[i].varId,
>                  &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
> -                            &(tmpdoubledata[indexInDoubleArray]) NCREQ2);
> +                            &(tmpdoubledata[indexInDoubleArray]), &requests[idxReq++]);
>              ERRORS(success, "Failed to read double data in loop");
>              // We need to increment the index in double array for the
>              // next subrange
> @@ -749,9 +750,9 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
>
>              // Do a partial read, in each subrange
>              // wait outside this loop
> -            success = NCFUNCAG2(_vara_float)(_fileId, vdatas[i].varId,
> +            success = NCFUNCREQG(_vara_float)(_fileId, vdatas[i].varId,
>                  &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
> -                            &(tmpfloatdata[indexInFloatArray]) NCREQ2);
> +                            &(tmpfloatdata[indexInFloatArray]), &requests[idxReq++]);
>              ERRORS(success, "Failed to read float data in loop");
>              // We need to increment the index in float array for the
>              // next subrange
> @@ -817,7 +818,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
>
>    // Finally, read into that space
>    int success;
> -  std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vdatas.size() * tstep_nums.size());
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      std::size_t sz = vdatas[i].sz;
>
> @@ -857,7 +857,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
>
>              success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
>                  &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
> -                            &(tmpdoubledata[indexInDoubleArray]) NCREQ);
> +                            &(tmpdoubledata[indexInDoubleArray]));
>              ERRORS(success, "Failed to read float data in loop");
>              // We need to increment the index in double array for the
>              // next subrange
> @@ -898,7 +898,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
>
>              success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId,
>                  &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
> -                            &(tmpfloatdata[indexInFloatArray]) NCREQ);
> +                            &(tmpfloatdata[indexInFloatArray]));
>              ERRORS(success, "Failed to read float data in loop");
>              // We need to increment the index in float array for the
>              // next subrange
> @@ -933,11 +933,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
>      }
>    }
>
> -#ifdef NCWAIT
> -  int success = ncmpi_wait_all(fileId, requests.size(), &requests[0], &statuss[0]);
> -  ERRORS(success, "Failed on wait_all.");
> -#endif
> -
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
>
> This diff is so big that we needed to truncate the remainder.
>
> https://bitbucket.org/fathomteam/moab/commits/2f191ca7a0ec/
> Changeset:   2f191ca7a0ec
> Branch:      None
> User:        vijaysm
> Date:        2013-09-13 17:43:47
> Summary:     Merge branch 'master' of bitbucket.org:vijaysm/moab
>
> Affected #:  0 files
>
>
>
> https://bitbucket.org/fathomteam/moab/commits/c1ba6897e098/
> Changeset:   c1ba6897e098
> Branch:      None
> User:        vijaysm
> Date:        2013-09-17 09:30:58
> Summary:     Merge branch 'master' of bitbucket.org:vijaysm/moab
>
> Affected #:  0 files
>
>
>
> https://bitbucket.org/fathomteam/moab/commits/6ad1e631bd2f/
> Changeset:   6ad1e631bd2f
> Branch:      None
> User:        vijaysm
> Date:        2013-09-26 23:49:07
> Summary:     Merge branch 'master' of bitbucket.org:vijaysm/moab
>
> Affected #:  0 files
>
>
>
> https://bitbucket.org/fathomteam/moab/commits/9351b0b63805/
> Changeset:   9351b0b63805
> Branch:      None
> User:        vijaysm
> Date:        2013-10-24 01:33:16
> Summary:     Merged fathomteam/moab into master
> Affected #:  31 files
>
> diff --git a/configure.ac b/configure.ac
> index cc1d3e0..937385d 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -557,8 +557,6 @@ AC_ARG_WITH([parmetis],
>                  ;;
>                 esac] )
>
> -
> -
>  ################################################################################
>  #                            Optional Libraries
>  ################################################################################
> @@ -740,6 +738,8 @@ AC_SUBST(ZOLTAN_LIBS)
>  AC_SUBST(ZOLTAN_LIB_FLAGS)
>  AC_SUBST(ZOLTAN_INC_FLAGS)
>
> +EXPORT_LDFLAGS="$ZOLTAN_LIB_FLAGS $EXPORT_LDFLAGS"
> +
>  ################################################################################
>  #                    VTK for qvdual and/or vtkMOABReader
>  ################################################################################
>
> diff --git a/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
> index d67ca27..9bca8a6 100644
> --- a/doc/MetaData/metadata.h
> +++ b/doc/MetaData/metadata.h
> @@ -208,6 +208,12 @@ to the variable name. Multiple time step values can be specified, separated from
>
>  Create a gather set (associated with tag GATHER_SET) on one processor with the specified rank, to duplicate entities on other processors. If the rank is not specified, it will be rank 0 by default. If an invalid rank is passed, no gather set will be created. Gather set is specially used by HOMME, MPAS, and any other unstructured grid.
>
> +<H3>no_mixed_elements </H3>
> +
> +Indicates that no mixed elements (e.g. pentagons and hexagons) should be created by the MPAS reader. If this option is used, a common parameter maxEdgesPerCell will be computed to be used across all
> +processors (instead of the one reported in the MPAS file header, which is usually 10), and each cell is created with maxEdgesPerCell edges. Any cell that has less actual edges will be padded by duplicating
> +the last vertex in the connectivity array. As a result, all created cells will be in one contiguous chunk.
> +
>  \ref md-contents "Top"
>
>    \section meta-references References
>
> diff --git a/doc/metadata_info.doc b/doc/metadata_info.doc
> index 6e3eb34..a143f91 100644
> Binary files a/doc/metadata_info.doc and b/doc/metadata_info.doc differ
>
> diff --git a/doc/metadata_info.pdf b/doc/metadata_info.pdf
> index 376aa51..d86a470 100644
> Binary files a/doc/metadata_info.pdf and b/doc/metadata_info.pdf differ
>
> diff --git a/itaps/iBase.h b/itaps/iBase.h
> index e61f92d..4af4f7b 100644
> --- a/itaps/iBase.h
> +++ b/itaps/iBase.h
> @@ -18,7 +18,7 @@
>   ******************************************************************************/
>  #define IBASE_VERSION_MAJOR 1
>  #define IBASE_VERSION_MINOR 4
> -#define IBASE_VERSION_PATCH 0
> +#define IBASE_VERSION_PATCH 1
>
>  /***************************************************************************//**
>   * \ingroup VersionNumbers
>
> diff --git a/itaps/igeom/FBiGeom-Defs.inc.in b/itaps/igeom/FBiGeom-Defs.inc.in
> index 54217e4..0ed147a 100644
> --- a/itaps/igeom/FBiGeom-Defs.inc.in
> +++ b/itaps/igeom/FBiGeom-Defs.inc.in
> @@ -15,7 +15,7 @@ FBIGEOM_INCLUDES = $(FBIGEOM_CPPFLAGS)
>  FBIGEOM_LIBS = $(FBIGEOM_LDFLAGS) -L$(MOAB_LIBDIR) \
>                 -L$(FBIGEOM_LIBDIR) -liMesh -lFBiGeomMOAB -lMOAB \
>                 @NETCDF_LIBS@ @HDF5_LIBS@ @LIBS@ \
> -               @CGM_LDFLAGS@ @CGM_LIBS@
> +               @CGM_LDFLAGS@ @CGM_LIBS@ @ZOLTAN_LIBS@
>
>  FBIGEOM_INCLUDEDIR1 = @abs_srcdir@
>  FBIGEOM_INCLUDEDIR2 = -I at abs_top_builddir@
>
> diff --git a/itaps/imesh/iMesh-Defs.inc.in b/itaps/imesh/iMesh-Defs.inc.in
> index 44418e6..b0b7f70 100644
> --- a/itaps/imesh/iMesh-Defs.inc.in
> +++ b/itaps/imesh/iMesh-Defs.inc.in
> @@ -15,7 +15,7 @@ IMESH_INCLUDES = $(IMESH_CPPFLAGS)
>  IMESH_LIBS = $(IMESH_LDFLAGS) -L$(MOAB_LIBDIR) \
>               -L$(IMESH_LIBDIR) -liMesh -lMOAB \
>               @NETCDF_LIBS@ @PNETCDF_LIBS@ @HDF5_LIBS@ @DAMSEL_LIBS@ @LIBS@ \
> -             @CGM_LDFLAGS@ @CGM_LIBS@ @CCMIO_LIBS@
> +             @CGM_LDFLAGS@ @CGM_LIBS@ @CCMIO_LIBS@ @ZOLTAN_LIBS@
>
>  IMESH_INCLUDEDIR = @abs_srcdir@
>  IMESH_INCLUDEDIR2 = -I at abs_builddir@ -I at abs_srcdir@/.. -I at abs_builddir@/.. -I at abs_top_builddir@/src
>
> diff --git a/moab.make.in b/moab.make.in
> index e6dc42d..45f80de 100644
> --- a/moab.make.in
> +++ b/moab.make.in
> @@ -8,13 +8,15 @@ MOAB_INCLUDES = -I at abs_srcdir@/src \
>                  -I at abs_srcdir@/src/parallel \
>                  -I at abs_builddir@/src/parallel
>
> +MOAB_INCLUDES += @ZOLTAN_INC_FLAGS@
> +
>  MOAB_CXXFLAGS = @CXXFLAGS@ @AM_CXXFLAGS@
>  MOAB_CFLAGS = @CFLAGS@ @AM_CFLAGS@
>  MOAB_FFLAGS = @FFLAGS@
>  MOAB_FCFLAGS = @FCFLAGS@
>  MOAB_LDFLAGS = @EXPORT_LDFLAGS@
>
> -MOAB_LIBS_LINK = ${MOAB_LDFLAGS} -L${MOAB_LIBDIR} -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@
> +MOAB_LIBS_LINK = ${MOAB_LDFLAGS} -L${MOAB_LIBDIR} -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@ @ZOLTAN_LIBS@
>
>  MOAB_CXX = @CXX@
>  MOAB_CC  = @CC@
>
> diff --git a/src/AEntityFactory.cpp b/src/AEntityFactory.cpp
> index 577162e..08ddb00 100644
> --- a/src/AEntityFactory.cpp
> +++ b/src/AEntityFactory.cpp
> @@ -820,6 +820,9 @@ ErrorCode AEntityFactory::get_down_adjacency_elements_poly(EntityHandle source_e
>        Range vrange, adj_edges;
>        vrange.insert(vertex_array[i]);
>        vrange.insert(vertex_array[i+1]);
> +      // account for padded polygons; if the vertices are the same, skip
> +      if (vrange.size() == 1)
> +        continue;
>        tmp_result = thisMB->get_adjacencies(vrange, 1, false, adj_edges);
>        if (MB_SUCCESS != tmp_result) result = tmp_result;
>        if (adj_edges.size() == 1) {
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index dc0c3f2..3a86984 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -205,6 +205,18 @@ nobase_libMOAB_la_include_HEADERS = \
>    MOAB_FCDefs.h \
>    MBCN_protos.h \
>    MBTagConventions.hpp
> +if ENABLE_mbzoltan
> +  libMOAB_la_SOURCES += $(srcdir)/../tools/mbzoltan/MBZoltan.cpp
> +  nobase_libMOAB_la_include_HEADERS += $(srcdir)/../tools/mbzoltan/MBZoltan.hpp
> +  AM_CPPFLAGS +=  $(ZOLTAN_INC_FLAGS) -DHAVE_ZOLTAN
> +  # not sure yet if this is needed; will see when linking io reader (MPAS so far)
> +  # the tool mbpart needed it, and it just includes MBZoltan.hpp; so it needs ways to find
> +  # the libraries zoltan depends on
> +  libMOAB_la_LIBADD += $(ZOLTAN_LIBS) $(ZOLTAN_LIB_FLAGS)
> +endif
> +if HAVE_CGM
> +  AM_CPPFLAGS += @CGM_CPPFLAGS@ -DCGM @MOAB_CGM_DEFINES@
> +endif
>
>  MBCN_protos.h: MBCN.h $(top_srcdir)/itaps/mkprotos.sh
>         $(AM_V_GEN)$(top_srcdir)/itaps/mkprotos.sh MBCN MOAB $< $@ MOAB_FCDefs.h
>
> diff --git a/src/MeshTopoUtil.cpp b/src/MeshTopoUtil.cpp
> index cef11e3..711cbf5 100644
> --- a/src/MeshTopoUtil.cpp
> +++ b/src/MeshTopoUtil.cpp
> @@ -468,24 +468,40 @@ ErrorCode MeshTopoUtil::get_bridge_adjacencies(const EntityHandle from_entity,
>
>    if (bridge_dim < from_dim) {
>        // looping over each sub-entity of dimension bridge_dim...
> -    EntityHandle bridge_verts[MAX_SUB_ENTITIES];
> -    int bridge_indices[MAX_SUB_ENTITIES];
> -    for (int i = 0; i < CN::NumSubEntities(from_type, bridge_dim); i++) {
> -
> -        // get the vertices making up this sub-entity
> -      int num_bridge_verts = CN::VerticesPerEntity( CN::SubEntityType( from_type, bridge_dim, i ) );
> -      CN::SubEntityVertexIndices( from_type, bridge_dim, i, bridge_indices );
> -      for (int j = 0; j < num_bridge_verts; ++j)
> -        bridge_verts[j]= connect[bridge_indices[j]];
> -      //CN::SubEntityConn(connect, from_type, bridge_dim, i, &bridge_verts[0], num_bridge_verts);
> -
> -        // get the to_dim entities adjacent
> -      to_ents.clear();
> -      ErrorCode tmp_result = mbImpl->get_adjacencies(bridge_verts, num_bridge_verts,
> -                                                       to_dim, false, to_ents, Interface::INTERSECT);
> -      if (MB_SUCCESS != tmp_result) result = tmp_result;
> -
> -      to_adjs.merge(to_ents);
> +    if (MBPOLYGON == from_type)
> +    {
> +      for (int i=0; i<num_connect; i++)
> +      {
> +        // loop over edges, and get the vertices
> +        EntityHandle verts_on_edge[2]={connect[i], connect[(i+1)%num_connect]};
> +        to_ents.clear();
> +        ErrorCode tmp_result = mbImpl->get_adjacencies(verts_on_edge, 2,
> +                        to_dim, false, to_ents, Interface::INTERSECT);
> +        if (MB_SUCCESS != tmp_result) result = tmp_result;
> +        to_adjs.merge(to_ents);
> +      }
> +    }
> +    else
> +    {
> +      EntityHandle bridge_verts[MAX_SUB_ENTITIES];
> +      int bridge_indices[MAX_SUB_ENTITIES];
> +      for (int i = 0; i < CN::NumSubEntities(from_type, bridge_dim); i++) {
> +
> +          // get the vertices making up this sub-entity
> +        int num_bridge_verts = CN::VerticesPerEntity( CN::SubEntityType( from_type, bridge_dim, i ) );
> +        CN::SubEntityVertexIndices( from_type, bridge_dim, i, bridge_indices );
> +        for (int j = 0; j < num_bridge_verts; ++j)
> +          bridge_verts[j]= connect[bridge_indices[j]];
> +        //CN::SubEntityConn(connect, from_type, bridge_dim, i, &bridge_verts[0], num_bridge_verts);
> +
> +          // get the to_dim entities adjacent
> +        to_ents.clear();
> +        ErrorCode tmp_result = mbImpl->get_adjacencies(bridge_verts, num_bridge_verts,
> +                                                         to_dim, false, to_ents, Interface::INTERSECT);
> +        if (MB_SUCCESS != tmp_result) result = tmp_result;
> +
> +        to_adjs.merge(to_ents);
> +      }
>      }
>
>    }
>
> diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
> index 1d42dde..12f5b89 100644
> --- a/src/ScdInterface.cpp
> +++ b/src/ScdInterface.cpp
> @@ -22,7 +22,7 @@
>  namespace moab
>  {
>
> -const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "sqijk", "trivial", "nopart"};
> +const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "sqijk", "trivial","rcbzoltan", "nopart"};
>
>  ScdInterface::ScdInterface(Interface *imp, bool boxes)
>          : mbImpl(imp),
>
> diff --git a/src/Skinner.cpp b/src/Skinner.cpp
> index c3c6b1b..02acf2c 100644
> --- a/src/Skinner.cpp
> +++ b/src/Skinner.cpp
> @@ -424,6 +424,7 @@ ErrorCode Skinner::find_skin_noadj(const Range &source_entities,
>    for(iter = source_entities.begin(); iter != end_iter; ++iter)
>    {
>      // get the connectivity of this entity
> +    int actual_num_nodes_polygon=0;
>      result = thisMB->get_connectivity(*iter, conn, num_nodes, false, &tmp_conn_vec);
>      if (MB_SUCCESS != result)
>        return result;
> @@ -434,7 +435,13 @@ ErrorCode Skinner::find_skin_noadj(const Range &source_entities,
>      // treat separately polygons (also, polyhedra will need special handling)
>      if (MBPOLYGON == type)
>      {
> -      num_sides = num_nodes;
> +      // treat padded polygons, if existing; count backwards, see how many of the last nodes are repeated
> +      // assume connectivity is fine, otherwise we could be in trouble
> +      actual_num_nodes_polygon = num_nodes;
> +      while (actual_num_nodes_polygon >= 3 &&
> +          conn[actual_num_nodes_polygon-1]==conn[actual_num_nodes_polygon-2])
> +        actual_num_nodes_polygon--;
> +      num_sides = actual_num_nodes_polygon;
>        sub_type = MBEDGE;
>        num_sub_nodes = 2;
>      }
> @@ -445,7 +452,9 @@ ErrorCode Skinner::find_skin_noadj(const Range &source_entities,
>        if(MBPOLYGON==type)
>        {
>          sub_conn[0] = conn[i];
> -        sub_conn[1] = conn[(i+1)%num_sides];
> +        sub_conn[1] = conn[i+1];
> +        if (i+1 == actual_num_nodes_polygon)
> +          sub_conn[1]=conn[0];
>        }
>        else
>        {
> @@ -1431,8 +1440,17 @@ ErrorCode Skinner::create_side( EntityHandle elem,
>      }
>      if (len == i)
>        return MB_FAILURE; // not found, big error
> +    // now, what if the polygon is padded?
> +    // the previous index is fine always. but the next one could be trouble :(
>      int prevIndex = (i+len-1)%len;
>      int nextIndex = (i+1)%len;
> +    // if the next index actually point to the same node, as current, it means it is padded
> +    if (conn[nextIndex]== conn[i])
> +    {
> +      // it really means we are at the end of proper nodes, the last nodes are repeated, so it should
> +      // be the first node
> +      nextIndex = 0; // this is the first node!
> +    }
>      EntityHandle conn2[2] = {side_conn[0], side_conn[1]};
>      if (conn[prevIndex]==side_conn[1])
>      {
> @@ -1617,9 +1635,12 @@ ErrorCode Skinner::find_skin_vertices_2D( Tag tag,
>          }
>        }
>
> -      const int prev_idx = (idx + len - 1)%len;
> +      // so it must be a MBPOLYGON
> +      const int prev_idx = (idx + len - 1)%len; // this should be fine, always, even for padded case
>        prev = conn[prev_idx];
>        next = conn[(idx+1)%len];
> +      if (next == conn[idx]) // it must be the padded case, so roll to the beginning
> +        next = conn[0];
>
>          // Insert sides (edges) in our list of candidate skin sides
>        adj_edges.insert( &prev, 1, *i, prev_idx );
>
> diff --git a/src/io/Makefile.am b/src/io/Makefile.am
> index bb5b7cb..968f47f 100644
> --- a/src/io/Makefile.am
> +++ b/src/io/Makefile.am
> @@ -39,6 +39,9 @@ if !NETCDF_FILE
>  endif
>  endif
>
> +if ENABLE_mbzoltan
> +  AM_CPPFLAGS += -DHAVE_ZOLTAN -I$(srcdir)/../../tools/mbzoltan $(ZOLTAN_INC_FLAGS)
> +endif
>  if HDF5_FILE
>    libmoabio_la_LIBADD += mhdf/libmhdf.la
>    MOAB_HDF5_SRCS = HDF5Common.cpp \
>
> diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
> index c0605e8..80f3a1e 100644
> --- a/src/io/NCHelperMPAS.cpp
> +++ b/src/io/NCHelperMPAS.cpp
> @@ -4,6 +4,10 @@
>  #include "moab/SpectralMeshTool.hpp"
>  #include "MBTagConventions.hpp"
>
> +#if HAVE_ZOLTAN
> +#include "MBZoltan.hpp"
> +#endif
> +
>  #include <cmath>
>
>  #define ERRORR(rval, str) \
> @@ -14,12 +18,13 @@
>
>  namespace moab {
>
> -const int MAX_EDGES_PER_CELL = 10;
> +const int DEFAULT_MAX_EDGES_PER_CELL = 10;
>
>  NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet)
>  : UcdNCHelper(readNC, fileId, opts, fileSet)
> -, maxCellEdges(MAX_EDGES_PER_CELL)
> +, maxEdgesPerCell(DEFAULT_MAX_EDGES_PER_CELL)
>  , numCellGroups(0)
> +, createGatherSet(false)
>  {
>  }
>
> @@ -44,12 +49,12 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
>    unsigned int idx;
>    std::vector<std::string>::iterator vit;
>
> -  // Get max edges per cell
> +  // Get max edges per cell reported in the MPAS file header
>    if ((vit = std::find(dimNames.begin(), dimNames.end(), "maxEdges")) != dimNames.end()) {
>      idx = vit - dimNames.begin();
> -    maxCellEdges = dimLens[idx];
> -    if (maxCellEdges > MAX_EDGES_PER_CELL) {
> -      ERRORR(MB_FAILURE, "maxEdges read from MPAS file has exceeded the limit");
> +    maxEdgesPerCell = dimLens[idx];
> +    if (maxEdgesPerCell > DEFAULT_MAX_EDGES_PER_CELL) {
> +      ERRORR(MB_FAILURE, "maxEdgesPerCell read from the MPAS file header has exceeded DEFAULT_MAX_EDGES_PER_CELL.");
>      }
>    }
>
> @@ -101,33 +106,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
>    levDim = idx;
>    nLevels = dimLens[idx];
>
> -  // Store xVertex values in xVertVals
>    std::map<std::string, ReadNC::VarData>::iterator vmit;
> -  if ((vmit = varInfo.find("xVertex")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
> -    rval = read_coordinate("xVertex", 0, nVertices - 1, xVertVals);
> -    ERRORR(rval, "Trouble reading 'xVertex' variable.");
> -  }
> -  else {
> -    ERRORR(MB_FAILURE, "Couldn't find 'xVertex' variable.");
> -  }
> -
> -  // Store yVertex values in yVertVals
> -  if ((vmit = varInfo.find("yVertex")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
> -    rval = read_coordinate("yVertex", 0, nVertices - 1, yVertVals);
> -    ERRORR(rval, "Trouble reading 'yVertex' variable.");
> -  }
> -  else {
> -    ERRORR(MB_FAILURE, "Couldn't find 'yVertex' variable.");
> -  }
> -
> -  // Store zVertex values in zVertVals
> -  if ((vmit = varInfo.find("zVertex")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
> -    rval = read_coordinate("zVertex", 0, nVertices - 1, zVertVals);
> -    ERRORR(rval, "Trouble reading 'zVertex' variable.");
> -  }
> -  else {
> -    ERRORR(MB_FAILURE, "Couldn't find 'zVertex' variable.");
> -  }
>
>    // Store time coordinate values in tVals
>    if (nTimeSteps > 0) {
> @@ -142,16 +121,6 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
>      }
>    }
>
> -  // Read vertices on each edge
> -  int verticesOnEdgeVarId;
> -  int success = NCFUNC(inq_varid)(_fileId, "verticesOnEdge", &verticesOnEdgeVarId);
> -  ERRORS(success, "Failed to get variable id of verticesOnEdge.");
> -  NCDF_SIZE tmp_starts[2] = {0, 0};
> -  NCDF_SIZE tmp_counts[2] = {static_cast<NCDF_SIZE>(nEdges), 2};
> -  verticesOnEdge.resize(nEdges * 2);
> -  success = NCFUNCAG(_vara_int)(_fileId, verticesOnEdgeVarId, tmp_starts, tmp_counts, &verticesOnEdge[0]);
> -  ERRORS(success, "Failed to read variable values of verticesOnEdge.");
> -
>    // Determine the entity location type of a variable
>    for (vmit = varInfo.begin(); vmit != varInfo.end(); ++vmit) {
>      ReadNC::VarData& vd = (*vmit).second;
> @@ -182,6 +151,14 @@ ErrorCode NCHelperMPAS::check_existing_mesh()
>    if (noMesh) {
>      ErrorCode rval;
>
> +    // Restore numCellGroups
> +    if (0 == numCellGroups) {
> +      Tag numCellGroupsTag;
> +      rval = mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag);
> +      if (MB_SUCCESS == rval)
> +        rval = mbImpl->tag_get_data(numCellGroupsTag, &_fileSet, 1, &numCellGroups);
> +    }
> +
>      if (localGidVerts.empty()) {
>        // Get all vertices from tmp_set (it is the input set in no_mesh scenario)
>        Range local_verts;
> @@ -243,20 +220,15 @@ ErrorCode NCHelperMPAS::check_existing_mesh()
>          std::copy(gids.rbegin(), gids.rend(), range_inserter(localGidCells));
>          nLocalCells = localGidCells.size();
>
> -        // Restore cellHandleToGlobalID
> -        Range::const_iterator rit;
> -        int i;
> -        for (rit = local_cells.begin(), i = 0; rit != local_cells.end(); ++rit, i++)
> -          cellHandleToGlobalID[*rit] = gids[i];
> +        if (numCellGroups > 1) {
> +          // Restore cellHandleToGlobalID
> +          Range::const_iterator rit;
> +          int i;
> +          for (rit = local_cells.begin(), i = 0; rit != local_cells.end(); ++rit, i++)
> +            cellHandleToGlobalID[*rit] = gids[i];
> +        }
>        }
>      }
> -
> -    // Restore numCellGroups
> -    if (0 == numCellGroups) {
> -      Tag numCellGroupsTag;
> -      rval = mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag);
> -      rval = mbImpl->tag_get_data(numCellGroupsTag, &_fileSet, 1, &numCellGroups);
> -    }
>    }
>
>    return MB_SUCCESS;
> @@ -265,9 +237,10 @@ ErrorCode NCHelperMPAS::check_existing_mesh()
>  ErrorCode NCHelperMPAS::create_mesh(Range& faces)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> -  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> -  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
>    int& gatherSetRank = _readNC->gatherSetRank;
> +  bool& noMixedElements = _readNC->noMixedElements;
> +  bool& noEdges = _readNC->noEdges;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
>
>    int rank = 0;
>    int procs = 1;
> @@ -281,325 +254,182 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
>  #endif
>
>    // Need to know whether we'll be creating gather mesh
> -  bool create_gathers = false;
>    if (rank == gatherSetRank)
> -    create_gathers = true;
> -
> -  // Compute the number of local cells on this proc
> -  nLocalCells = int(std::floor(1.0 * nCells / procs));
> -  // start_cell_idx is the starting global cell index in the MPAS file for this proc
> -  int start_cell_idx = rank * nLocalCells;
> -  // iextra = # cells extra after equal split over procs
> -  int iextra = nCells % procs;
> -  if (rank < iextra)
> -    nLocalCells++;
> -  start_cell_idx += std::min(rank, iextra);
> -  start_cell_idx++; // 0 based -> 1 based
> -  localGidCells.insert(start_cell_idx, start_cell_idx + nLocalCells - 1);
> +    createGatherSet = true;
> +
> +  if (procs >= 2) {
> +    // Compute the number of local cells on this proc
> +    nLocalCells = int(std::floor(1.0 * nCells / procs));
> +
> +    // The starting global cell index in the MPAS file for this proc
> +    int start_cell_idx = rank * nLocalCells;
> +
> +    // Number of extra cells after equal split over procs
> +    int iextra = nCells % procs;
>
> -  // Read number of edges on each local cell
> +    // Allocate extra cells over procs
> +    if (rank < iextra)
> +      nLocalCells++;
> +    start_cell_idx += std::min(rank, iextra);
> +
> +    start_cell_idx++; // 0 based -> 1 based
> +
> +    // Redistribute local cells after trivial partition (e.g. apply Zoltan partition)
> +    ErrorCode rval = redistribute_local_cells(start_cell_idx);
> +    ERRORR(rval, "Failed to redistribute local cells after trivial partition.");
> +  }
> +  else {
> +    nLocalCells = nCells;
> +    localGidCells.insert(1, nLocalCells);
> +  }
> +
> +  // Read number of edges on each local cell, to calculate actual maxEdgesPerCell
>    int nEdgesOnCellVarId;
>    int success = NCFUNC(inq_varid)(_fileId, "nEdgesOnCell", &nEdgesOnCellVarId);
>    ERRORS(success, "Failed to get variable id of nEdgesOnCell.");
> -  NCDF_SIZE tmp_starts_1[1] = {static_cast<NCDF_SIZE>(start_cell_idx - 1)};
> -  NCDF_SIZE tmp_counts_1[1] = {static_cast<NCDF_SIZE>(nLocalCells)};
>    std::vector<int> num_edges_on_local_cells(nLocalCells);
> -  success = NCFUNCAG(_vara_int)(_fileId, nEdgesOnCellVarId, tmp_starts_1, tmp_counts_1, &num_edges_on_local_cells[0]);
> -  ERRORS(success, "Failed to read variable values of nEdgesOnCell.");
> +#ifdef PNETCDF_FILE
> +  size_t nb_reads = localGidCells.psize();
> +  std::vector<int> requests(nb_reads);
> +  std::vector<int> statuss(nb_reads);
> +  size_t idxReq = 0;
> +#endif
> +  size_t indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidCells.pair_begin();
> +       pair_iter != localGidCells.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_start = (NCDF_SIZE) (starth - 1);
> +    NCDF_SIZE read_count = (NCDF_SIZE) (endh - starth + 1);
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count,
> +                                      &(num_edges_on_local_cells[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count,
> +                                      &(num_edges_on_local_cells[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read nEdgesOnCell data in a loop");
>
> -  // Read vertices on each local cell (connectivity)
> -  int verticesOnCellVarId;
> -  success = NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCellVarId);
> -  ERRORS(success, "Failed to get variable id of verticesOnCell.");
> -  NCDF_SIZE tmp_starts_2[2] = {static_cast<NCDF_SIZE>(start_cell_idx - 1), 0};
> -  NCDF_SIZE tmp_counts_2[2] = {static_cast<NCDF_SIZE>(nLocalCells), maxCellEdges};
> -  std::vector<int> vertices_on_local_cells(nLocalCells * maxCellEdges);
> -  success = NCFUNCAG(_vara_int)(_fileId, verticesOnCellVarId, tmp_starts_2, tmp_counts_2, &vertices_on_local_cells[0]);
> -  ERRORS(success, "Failed to read variable values of verticesOnCell.");
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1);
> +  }
>
> -  // Read edges on each local cell
> -  int edgesOnCellVarId;
> -  success = NCFUNC(inq_varid)(_fileId, "edgesOnCell", &edgesOnCellVarId);
> -  ERRORS(success, "Failed to get variable id of edgesOnCell.");
> -  NCDF_SIZE tmp_starts_3[2] = {static_cast<NCDF_SIZE>(start_cell_idx - 1), 0};
> -  NCDF_SIZE tmp_counts_3[2] = {static_cast<NCDF_SIZE>(nLocalCells), maxCellEdges};
> -  std::vector<int> edges_on_local_cells(nLocalCells * maxCellEdges);
> -  success = NCFUNCAG(_vara_int)(_fileId, edgesOnCellVarId, tmp_starts_3, tmp_counts_3, &edges_on_local_cells[0]);
> -  ERRORS(success, "Failed to read variable values of edgesOnCell.");
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
>
> -  // Divide local cells into groups based on the number of edges
> -  std::vector<int> local_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
> -  for (int i = 0; i < nLocalCells; i++) {
> -    int cell_index = start_cell_idx + i; // Global cell index
> -    int num_edges = num_edges_on_local_cells[i];
> -    local_cells_with_n_edges[num_edges].push_back(cell_index);
> -  }
> +  // Get local maxEdgesPerCell on this proc
> +  int local_max_edges_per_cell = *(std::max_element(num_edges_on_local_cells.begin(), num_edges_on_local_cells.end()));
> +  maxEdgesPerCell = local_max_edges_per_cell;
>
> -  // For each non-empty cell group, create cells and set connectivity array initially based on file ids
> -  ErrorCode rval;
> -  EntityHandle start_element;
> -  EntityHandle* conn_arr_local_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
> -  Range tmp_range;
> -  void* data;
> -  int count;
> -  int* gid_data;
> -  std::set<int> local_verts_set;
> -  std::set<int> local_edges_set;
> -  numCellGroups = 0;
> -  for (int i = 3; i <= maxCellEdges; i++) {
> -    int num_cells = local_cells_with_n_edges[i].size();
> -    if (num_cells > 0) {
> -      numCellGroups++;
> -
> -      rval = _readNC->readMeshIface->get_element_connect(num_cells, i, MBPOLYGON, 0, start_element, conn_arr_local_cells_with_n_edges[i], num_cells);
> -      ERRORR(rval, "Couldn't create local cells in MPAS mesh.");
> -      Range local_cell_range(start_element, start_element + num_cells - 1);
> -      tmp_range.insert(start_element, start_element + num_cells - 1);
> -      faces.insert(start_element, start_element + num_cells - 1);
> -
> -      // Get ptr to gid memory for local cells
> -      rval = mbImpl->tag_iterate(mGlobalIdTag, local_cell_range.begin(), local_cell_range.end(), count, data);
> -      ERRORR(rval, "Failed to get tag iterator on global id tag.");
> -      assert(count == (int) num_cells);
> -      gid_data = (int*) data;
> -      std::copy(local_cells_with_n_edges[i].begin(), local_cells_with_n_edges[i].end(), gid_data);
> -
> -      for (int j = 0; j < num_cells; j++) {
> -        int cell_idx = local_cells_with_n_edges[i][j]; // Global cell index
> -        cellHandleToGlobalID[start_element + j] = cell_idx;
> -        cell_idx -= start_cell_idx; // Local cell index
> -        for (int k = 0; k < i; k++) {
> -          conn_arr_local_cells_with_n_edges[i][i * j + k] = vertices_on_local_cells[cell_idx * maxCellEdges + k];
> -          local_verts_set.insert(vertices_on_local_cells[cell_idx * maxCellEdges + k]);
> -          local_edges_set.insert(edges_on_local_cells[cell_idx * maxCellEdges + k]);
> -        }
> -      }
> -    }
> +  // If parallel, do a MPI_Allreduce to get global maxEdgesPerCell across all procs
> +#ifdef USE_MPI
> +  if (procs > 1) {
> +    int global_max_edges_per_cell;
> +    ParallelComm*& myPcomm = _readNC->myPcomm;
> +    MPI_Allreduce(&local_max_edges_per_cell, &global_max_edges_per_cell, 1, MPI_INTEGER, MPI_MAX, myPcomm->proc_config().proc_comm());
> +    assert(local_max_edges_per_cell <= global_max_edges_per_cell);
> +    maxEdgesPerCell = global_max_edges_per_cell;
> +    if (0 == rank)
> +      dbgOut.tprintf(1, "  global_max_edges_per_cell = %d\n", global_max_edges_per_cell);
>    }
> +#endif
>
> -  // Set tag for numCellGroups
> -  Tag numCellGroupsTag = 0;
> -  rval = mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> -  ERRORR(rval, "Trouble creating __NUM_CELL_GROUPS tag.");
> -  rval = mbImpl->tag_set_data(numCellGroupsTag, &_fileSet, 1, &numCellGroups);
> -  ERRORR(rval, "Trouble setting data for __NUM_CELL_GROUPS tag.");
> +  // Read vertices on each local cell, to get localGidVerts and cell connectivity later
> +  int verticesOnCellVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of verticesOnCell.");
> +  std::vector<int> vertices_on_local_cells(nLocalCells * maxEdgesPerCell);
> +#ifdef PNETCDF_FILE
> +  idxReq = 0;
> +#endif
> +  indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidCells.pair_begin();
> +       pair_iter != localGidCells.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_starts[2] = {static_cast<NCDF_SIZE>(starth - 1), 0};
> +    NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(endh - starth + 1), maxEdgesPerCell};
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts,
> +                                      &(vertices_on_local_cells[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts,
> +                                      &(vertices_on_local_cells[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read verticesOnCell data in a loop");
>
> -  // Collect localGid for vertices
> -  std::copy(local_verts_set.rbegin(), local_verts_set.rend(), range_inserter(localGidVerts));
> -  nLocalVertices = localGidVerts.size();
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1) * maxEdgesPerCell;
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
>
>    // Create local vertices
>    EntityHandle start_vertex;
> -  std::vector<double*> arrays;
> -  rval = _readNC->readMeshIface->get_node_coords(3, nLocalVertices, 0, start_vertex, arrays,
> -                                        // Might have to create gather mesh later
> -                                        (create_gathers ? nLocalVertices + nVertices : nLocalVertices));
> -  ERRORR(rval, "Couldn't create local vertices in MPAS mesh.");
> -  tmp_range.insert(start_vertex, start_vertex + nLocalVertices - 1);
> +  ErrorCode rval = create_local_vertices(vertices_on_local_cells, start_vertex);
> +  ERRORR(rval, "Failed to create local vertices for MPAS mesh.");
>
> -  // Set coordinates for local vertices
> -  double* xptr = arrays[0];
> -  double* yptr = arrays[1];
> -  double* zptr = arrays[2];
> -  Range::const_iterator rit;
> -  int vert_idx;
> -  for (vert_idx = 0, rit = localGidVerts.begin(); vert_idx < nLocalVertices; vert_idx++, ++rit) {
> -    assert(*rit < xVertVals.size() + 1);
> -    xptr[vert_idx] = xVertVals[(*rit) - 1];
> -    yptr[vert_idx] = yVertVals[(*rit) - 1];
> -    zptr[vert_idx] = zVertVals[(*rit) - 1];
> +  // Create local edges (unless NO_EDGES read option is set)
> +  if (!noEdges) {
> +    rval = create_local_edges(start_vertex);
> +    ERRORR(rval, "Failed to create local edges for MPAS mesh.");
>    }
>
> -  // Get ptr to gid memory for local vertices
> -  Range local_verts_range(start_vertex, start_vertex + nLocalVertices - 1);
> -  rval = mbImpl->tag_iterate(mGlobalIdTag, local_verts_range.begin(), local_verts_range.end(), count, data);
> -  ERRORR(rval, "Failed to get tag iterator on global id tag.");
> -  assert(count == (int) nLocalVertices);
> -  gid_data = (int*) data;
> -  std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
> -
> -  // Duplicate global id data, which will be used to resolve sharing
> -  if (mpFileIdTag) {
> -    rval = mbImpl->tag_iterate(*mpFileIdTag, local_verts_range.begin(), local_verts_range.end(), count, data);
> -    ERRORR(rval, "Failed to get tag iterator on file id tag.");
> -    assert(count == (int) nLocalVertices);
> -    gid_data = (int*) data;
> -    std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
> +  // Create local cells, either unpadded or padded
> +  if (noMixedElements) {
> +    rval = create_padded_local_cells(vertices_on_local_cells, num_edges_on_local_cells, start_vertex, faces);
> +    ERRORR(rval, "Failed to create padded local cells for MPAS mesh.");
>    }
> -
> -  // Create map from file ids to vertex handles
> -  std::map<EntityHandle, EntityHandle> vert_handles;
> -  for (rit = localGidVerts.begin(), vert_idx = 0; rit != localGidVerts.end(); ++rit, vert_idx++)
> -    vert_handles[*rit] = start_vertex + vert_idx;
> -
> -  // For each non-empty cell group, set connectivity array with proper local vertices handles
> -  for (int i = 3; i <= maxCellEdges; i++) {
> -    int num_cells = local_cells_with_n_edges[i].size();
> -    if (num_cells > 0) {
> -      for (int j = 0; j < num_cells; j++) {
> -        for (int k = 0; k < i; k++) {
> -          EntityHandle global_vert_id = conn_arr_local_cells_with_n_edges[i][i * j + k];
> -          conn_arr_local_cells_with_n_edges[i][i * j + k] = vert_handles[global_vert_id];
> -        }
> -      }
> -    }
> -  }
> -
> -  // Collect localGid for edges
> -  std::copy(local_edges_set.rbegin(), local_edges_set.rend(), range_inserter(localGidEdges));
> -  nLocalEdges = localGidEdges.size();
> -
> -  // Create local edges
> -  EntityHandle start_edge;
> -  EntityHandle* conn_arr_edges;
> -  rval = _readNC->readMeshIface->get_element_connect(nLocalEdges, 2, MBEDGE, 0, start_edge, conn_arr_edges,
> -                                            // Might have to create gather mesh later
> -                                            (create_gathers ? nLocalEdges + nEdges : nLocalEdges));
> -  ERRORR(rval, "Couldn't create local edges in MPAS mesh.");
> -  Range local_edges_range(start_edge, start_edge + nLocalEdges - 1);
> -  tmp_range.insert(start_edge, start_edge + nLocalEdges - 1);
> -
> -  // Set vertices for local edges
> -  int edge_idx;
> -  for (rit = localGidEdges.begin(), edge_idx = 0; rit != localGidEdges.end(); ++rit, edge_idx++) {
> -    EntityHandle gloabl_edge_id = *rit;
> -    EntityHandle gloabl_vert_id_1 = verticesOnEdge[(gloabl_edge_id - 1) * 2 + 0];
> -    EntityHandle gloabl_vert_id_2 = verticesOnEdge[(gloabl_edge_id - 1) * 2 + 1];
> -    conn_arr_edges[edge_idx * 2 + 0] = vert_handles[gloabl_vert_id_1];
> -    conn_arr_edges[edge_idx * 2 + 1] = vert_handles[gloabl_vert_id_2];
> +  else {
> +    rval = create_local_cells(vertices_on_local_cells, num_edges_on_local_cells, start_vertex, faces);
> +    ERRORR(rval, "Failed to create local cells for MPAS mesh.");
>    }
>
> -  // Get ptr to gid memory for edges
> -  rval = mbImpl->tag_iterate(mGlobalIdTag, local_edges_range.begin(), local_edges_range.end(), count, data);
> -  ERRORR(rval, "Failed to get tag iterator on global id tag.");
> -  assert(count == (int) nLocalEdges);
> -  gid_data = (int*) data;
> -  std::copy(localGidEdges.begin(), localGidEdges.end(), gid_data);
> -
> -  // Add new vertices, elements and edges to the file set
> -  rval = _readNC->mbImpl->add_entities(_fileSet, tmp_range);
> -  ERRORR(rval, "Couldn't add new vertices/faces/edges to file set.");
> +  // Set tag for numCellGroups
> +  Tag numCellGroupsTag = 0;
> +  rval = mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER, numCellGroupsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
> +  ERRORR(rval, "Failed to get __NUM_CELL_GROUPS tag.");
> +  rval = mbImpl->tag_set_data(numCellGroupsTag, &_fileSet, 1, &numCellGroups);
> +  ERRORR(rval, "Failed to set data for __NUM_CELL_GROUPS tag.");
>
> -  if (create_gathers) {
> +  if (createGatherSet) {
>      EntityHandle gather_set;
>      rval = _readNC->readMeshIface->create_gather_set(gather_set);
> -    ERRORR(rval, "Trouble creating gather set.");
> -
> -    // Create gather vertices
> -    arrays.clear();
> -    // Don't need to specify allocation number here, because we know enough verts were created before
> -    rval = _readNC->readMeshIface->get_node_coords(3, nVertices, 0, start_vertex, arrays);
> -    ERRORR(rval, "Couldn't create vertices in MPAS mesh for gather set.");
> -    Range gather_verts_range(start_vertex, start_vertex + nVertices - 1);
> -
> -    xptr = arrays[0];
> -    yptr = arrays[1];
> -    zptr = arrays[2];
> -    for (vert_idx = 0; vert_idx < nVertices; vert_idx++) {
> -      xptr[vert_idx] = xVertVals[vert_idx];
> -      yptr[vert_idx] = yVertVals[vert_idx];
> -      zptr[vert_idx] = zVertVals[vert_idx];
> -    }
> +    ERRORR(rval, "Failed to create gather set.");
>
> -    // Get ptr to gid memory for gather vertices
> -    rval = mbImpl->tag_iterate(mGlobalIdTag, gather_verts_range.begin(), gather_verts_range.end(), count, data);
> -    ERRORR(rval, "Failed to get tag iterator on global id tag..");
> -    assert(count == nVertices);
> -    gid_data = (int*) data;
> -    for (int j = 1; j <= nVertices; j++)
> -      gid_data[j - 1] = j;
> -    // Set the file id tag too, it should be bigger something not interfering with global id
> -    if (mpFileIdTag) {
> -      rval = mbImpl->tag_iterate(*mpFileIdTag, gather_verts_range.begin(), gather_verts_range.end(), count, data);
> -      ERRORR(rval, "Failed to get tag iterator on file id tag.");
> -      assert(count == nVertices);
> -      gid_data = (int*) data;
> -      for (int j = 1; j <= nVertices; j++)
> -        gid_data[j - 1] = nVertices + j; // Bigger than global id tag
> -    }
> -
> -    rval = mbImpl->add_entities(gather_set, gather_verts_range);
> -    ERRORR(rval, "Couldn't add vertices to gather set.");
> +    // Create gather set vertices
> +    EntityHandle start_gather_set_vertex;
> +    rval = create_gather_set_vertices(gather_set, start_gather_set_vertex);
> +    ERRORR(rval, "Failed to create gather set vertices for MPAS mesh");
>
> -    // Read number of edges on each gather cell
> -    std::vector<int> num_edges_on_gather_cells(nCells);
> -    tmp_starts_1[0] = 0;
> -    tmp_counts_1[0] = static_cast<NCDF_SIZE>(nCells);
> -#ifdef PNETCDF_FILE
> -    // Enter independent I/O mode, since this read is only for the gather processor
> -    success = NCFUNC(begin_indep_data)(_fileId);
> -    ERRORS(success, "Failed to begin independent I/O mode.");
> -    success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, tmp_starts_1, tmp_counts_1, &num_edges_on_gather_cells[0]);
> -    ERRORS(success, "Failed to read variable values of nEdgesOnCell.");
> -    success = NCFUNC(end_indep_data)(_fileId);
> -    ERRORS(success, "Failed to end independent I/O mode.");
> -#else
> -    success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, tmp_starts_1, tmp_counts_1, &num_edges_on_gather_cells[0]);
> -    ERRORS(success, "Failed to read variable values of nEdgesOnCell.");
> -#endif
> -    // Read vertices on each gather cell (connectivity)
> -    std::vector<int> vertices_on_gather_cells(nCells * maxCellEdges);
> -    tmp_starts_2[0] = 0;
> -    tmp_starts_2[1] = 0;
> -    tmp_counts_2[0] = nCells;
> -    tmp_counts_2[1] = maxCellEdges;
> -#ifdef PNETCDF_FILE
> -    // Enter independent I/O mode, since this read is only for the gather processor
> -    success = NCFUNC(begin_indep_data)(_fileId);
> -    ERRORS(success, "Failed to begin independent I/O mode.");
> -    success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, tmp_starts_2, tmp_counts_2, &vertices_on_gather_cells[0]);
> -    ERRORS(success, "Failed to read variable values of verticesOnCell.");
> -    success = NCFUNC(end_indep_data)(_fileId);
> -    ERRORS(success, "Failed to end independent I/O mode.");
> -#else
> -    success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, tmp_starts_2, tmp_counts_2, &vertices_on_gather_cells[0]);
> -    ERRORS(success, "Failed to read variable values of verticesOnCell.");
> -#endif
> -
> -    // Divide gather cells into groups based on the number of edges
> -    std::vector<int> gather_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
> -    for (int i = 0; i < nCells; i++) {
> -      int num_edges = num_edges_on_gather_cells[i];
> -      gather_cells_with_n_edges[num_edges].push_back(i + 1); // 0 based -> 1 based
> +    // Create gather set edges (unless NO_EDGES read option is set)
> +    if (!noEdges) {
> +      rval = create_gather_set_edges(gather_set, start_gather_set_vertex);
> +      ERRORR(rval, "Failed to create gather set edges for MPAS mesh.");
>      }
>
> -    // For each non-empty cell group, create cells and set connectivity array
> -    EntityHandle* conn_arr_gather_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
> -    Range gather_cells_range;
> -    for (int i = 3; i <= maxCellEdges; i++) {
> -      int num_cells = gather_cells_with_n_edges[i].size();
> -      if (num_cells > 0) {
> -        rval = _readNC->readMeshIface->get_element_connect(num_cells, i, MBPOLYGON, 0, start_element, conn_arr_gather_cells_with_n_edges[i], num_cells);
> -        ERRORR(rval, "Couldn't create cells in MPAS mesh for gather set.");
> -        gather_cells_range.insert(start_element, start_element + num_cells - 1);
> -        for (int j = 0; j < num_cells; j++) {
> -          int cell_idx = gather_cells_with_n_edges[i][j]; // Global cell index
> -          cell_idx--; // 1 based -> 0 based
> -          for (int k = 0; k < i; k++)
> -            // Connectivity array is shifted by where the gather verts start
> -            conn_arr_gather_cells_with_n_edges[i][i * j + k] = (start_vertex - 1) + vertices_on_gather_cells[cell_idx * maxCellEdges + k];
> -        }
> -      }
> +    // Create gather set cells, either unpadded or padded
> +    if (noMixedElements) {
> +      rval = create_padded_gather_set_cells(gather_set, start_gather_set_vertex);
> +      ERRORR(rval, "Failed to create padded gather set cells for MPAS mesh.");
> +    }
> +    else {
> +      rval = create_gather_set_cells(gather_set, start_gather_set_vertex);
> +      ERRORR(rval, "Failed to create gather set cells for MPAS mesh.");
>      }
> -
> -    rval = mbImpl->add_entities(gather_set, gather_cells_range);
> -    ERRORR(rval, "Couldn't add cells to gather set.");
> -
> -    // Create gather edges
> -    EntityHandle* conn_arr_gather_edges;
> -
> -    // Don't need to specify allocation number here, because we know enough edges were created before
> -    rval = _readNC->readMeshIface->get_element_connect(nEdges, 2, MBEDGE, 0, start_edge, conn_arr_gather_edges);
> -    ERRORR(rval, "Couldn't create edges in MPAS mesh for gather set.");
> -    Range gather_edges_range(start_edge, start_edge + nEdges - 1);
> -
> -    std::copy(verticesOnEdge.begin(), verticesOnEdge.end(), conn_arr_gather_edges);
> -    for (int i = 0; i < 2 * nEdges; i++)
> -      // Connectivity array is shifted by where the gather verts start
> -      conn_arr_gather_edges[i] += start_vertex - 1;
> -
> -    rval = mbImpl->add_entities(gather_set, gather_edges_range);
> -    ERRORR(rval, "Couldn't add edges to gather set.");
>    }
>
>    return MB_SUCCESS;
> @@ -615,8 +445,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
>    if (var_names.empty()) {
>      for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
>        ReadNC::VarData vd = (*mit).second;
> -      if (3 == vd.varDims.size())
> -      {
> +      if (3 == vd.varDims.size()) {
>          if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
>              vd.varDims.end(), cDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), levDim)
>              != vd.varDims.end()))
> @@ -667,6 +496,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
>      for (int i = 0; i < nTimeSteps; i++)
>        tstep_nums.push_back(i);
>    }
> +
>    if (!tstep_nums.empty()) {
>      for (unsigned int i = 0; i < vdatas.size(); i++) {
>        vdatas[i].varTags.resize(tstep_nums.size(), 0);
> @@ -698,6 +528,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
>    std::vector<int>& dimLens = _readNC->dimLens;
> +  bool& noEdges = _readNC->noEdges;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = MB_SUCCESS;
> @@ -736,6 +567,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
>  #endif
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
> +      continue;
> +
>      vdatas[i].numLev = nLevels;
>
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
> @@ -790,14 +624,16 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
>        assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
>
>        // Get ptr to tag space
> -      if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1)
> +      if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1) {
> +        // For a cell variable that is NOT on one contiguous chunk of faces, defer its tag space allocation
>          vdatas[i].varDatas[t] = NULL;
> +      }
>        else {
>          assert(1 == range->psize());
>          void* data;
>          int count;
>          rval = mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), range->end(), count, data);
> -        ERRORR(rval, "Failed to get tag iterator.");
> +        ERRORR(rval, "Failed to iterate tag.");
>          assert((unsigned)count == range->size());
>          vdatas[i].varDatas[t] = data;
>        }
> @@ -817,6 +653,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
>  ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> +  bool& noEdges = _readNC->noEdges;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = read_ucd_variable_to_nonset_allocate(vdatas, tstep_nums);
> @@ -827,6 +664,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
>    Range* pLocalGid = NULL;
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
> +      continue;
> +
>      switch (vdatas[i].entLoc) {
>        case ReadNC::ENTLOCVERT:
>          pLocalGid = &localGidVerts;
> @@ -893,15 +733,15 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
>            success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
>            ERRORS(success, "Failed on wait_all.");
>
> -          // Local cells are grouped by the number of edges on each cell, e.g. 5, 6 or 7
> -          // Tags created for cell variables may have to read data from different groups
>            if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1) {
> +            // For a cell variable that is NOT on one contiguous chunk of faces, allocate tag space for
> +            // each cell group, and utilize cellHandleToGlobalID map to read tag data
>              Range::iterator iter = facesOwned.begin();
>              while (iter != facesOwned.end()) {
>                int count;
>                void* ptr;
>                rval = mbImpl->tag_iterate(vdatas[i].varTags[t], iter, facesOwned.end(), count, ptr);
> -              ERRORR(rval, "Failed to get tag iterator.");
> +              ERRORR(rval, "Failed to iterate tag on owned faces.");
>
>                for (int j = 0; j < count; j++) {
>                  int cell_idx = cellHandleToGlobalID[*(iter + j)]; // Global cell index
> @@ -943,6 +783,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
>    }
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
> +      continue;
> +
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
>        ErrorCode tmp_rval = convert_variable(vdatas[i], t);
> @@ -964,6 +807,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
>  ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
>  {
>    Interface*& mbImpl = _readNC->mbImpl;
> +  bool& noEdges = _readNC->noEdges;
>    DebugOutput& dbgOut = _readNC->dbgOut;
>
>    ErrorCode rval = read_ucd_variable_to_nonset_allocate(vdatas, tstep_nums);
> @@ -974,6 +818,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
>    Range* pLocalGid = NULL;
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
> +      continue;
> +
>      switch (vdatas[i].entLoc) {
>        case ReadNC::ENTLOCVERT:
>          pLocalGid = &localGidVerts;
> @@ -1030,15 +877,15 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
>            }
>            assert(ic == pLocalGid->psize());
>
> -          // Local cells are grouped by the number of edges on each cell, e.g. 5, 6 or 7
> -          // Tags created for cell variables may have to read data from different groups
>            if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1) {
> +            // For a cell variable that is NOT on one contiguous chunk of faces, allocate tag space for
> +            // each cell group, and utilize cellHandleToGlobalID map to read tag data
>              Range::iterator iter = facesOwned.begin();
>              while (iter != facesOwned.end()) {
>                int count;
>                void* ptr;
>                rval = mbImpl->tag_iterate(vdatas[i].varTags[t], iter, facesOwned.end(), count, ptr);
> -              ERRORR(rval, "Failed to get tag iterator.");
> +              ERRORR(rval, "Failed to iterate tag on owned faces.");
>
>                for (int j = 0; j < count; j++) {
>                  int cell_idx = cellHandleToGlobalID[*(iter + j)]; // Global cell index
> @@ -1080,6 +927,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
>    }
>
>    for (unsigned int i = 0; i < vdatas.size(); i++) {
> +    if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
> +      continue;
> +
>      for (unsigned int t = 0; t < tstep_nums.size(); t++) {
>        dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
>        ErrorCode tmp_rval = convert_variable(vdatas[i], t);
> @@ -1100,4 +950,773 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
>  }
>  #endif
>
> +ErrorCode NCHelperMPAS::redistribute_local_cells(int start_cell_idx)
> +{
> +  // If possible, apply Zoltan partition
> +  if (_readNC->partMethod == ScdParData::RCBZOLTAN) {
> +#if defined(USE_MPI) && defined(PNETCDF_FILE) && defined(HAVE_ZOLTAN)
> +    // Read x coordinates of cell centers
> +    int xCellVarId;
> +    int success = NCFUNC(inq_varid)(_fileId, "xCell", &xCellVarId);
> +    ERRORS(success, "Failed to get variable id of xCell.");
> +    std::vector<double> xCell(nLocalCells);
> +    NCDF_SIZE read_start = 0;
> +    NCDF_SIZE read_count = static_cast<NCDF_SIZE>(nLocalCells);
> +    success = NCFUNCAG(_vara_double)(_fileId, xCellVarId, &read_start, &read_count, &xCell[0]);
> +    ERRORS(success, "Failed to read xCell data.");
> +
> +    // Read y coordinates of cell centers
> +    int yCellVarId;
> +    success = NCFUNC(inq_varid)(_fileId, "yCell", &yCellVarId);
> +    ERRORS(success, "Failed to get variable id of yCell.");
> +    std::vector<double> yCell(nLocalCells);
> +    success = NCFUNCAG(_vara_double)(_fileId, yCellVarId, &read_start, &read_count, &yCell[0]);
> +    ERRORS(success, "Failed to read yCell data.");
> +
> +    // Read z coordinates of cell centers
> +    int zCellVarId;
> +    success = NCFUNC(inq_varid)(_fileId, "zCell", &zCellVarId);
> +    ERRORS(success, "Failed to get variable id of zCell.");
> +    std::vector<double> zCell(nLocalCells);
> +    success = NCFUNCAG(_vara_double)(_fileId, zCellVarId, &read_start, &read_count, &zCell[0]);
> +    ERRORS(success, "Failed to read zCell data.");
> +
> +    // Zoltan partition using RCB; maybe more studies would be good, as to which partition
> +    // is better
> +    Interface*& mbImpl = _readNC->mbImpl;
> +    DebugOutput& dbgOut = _readNC->dbgOut;
> +    MBZoltan* mbZTool = new MBZoltan(mbImpl, false, 0, NULL);
> +    ErrorCode rval = mbZTool->repartition(xCell, yCell, zCell, start_cell_idx, "RCB", localGidCells);
> +    //delete mbZTool;
> +    ERRORR(rval, "Error in Zoltan partitioning.");
> +
> +    dbgOut.tprintf(1, "After Zoltan partitioning, localGidCells.psize() = %d\n", (int)localGidCells.psize());
> +    dbgOut.tprintf(1, "                           localGidCells.size() = %d\n", (int)localGidCells.size());
> +
> +    // This is important: local cells are now redistributed, so nLocalCells might be different!
> +    nLocalCells = localGidCells.size();
> +
> +    return MB_SUCCESS;
> +#endif
> +  }
> +
> +  // By default, apply trivial partition
> +  localGidCells.insert(start_cell_idx, start_cell_idx + nLocalCells - 1);
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_local_vertices(const std::vector<int>& vertices_on_local_cells, EntityHandle& start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  // Make a copy of vertices_on_local_cells for sorting (keep original one to set cell connectivity later)
> +  std::vector<int> vertices_on_local_cells_sorted(vertices_on_local_cells);
> +  std::sort(vertices_on_local_cells_sorted.begin(), vertices_on_local_cells_sorted.end());
> +  std::copy(vertices_on_local_cells_sorted.rbegin(), vertices_on_local_cells_sorted.rend(), range_inserter(localGidVerts));
> +  nLocalVertices = localGidVerts.size();
> +
> +  dbgOut.tprintf(1, "   localGidVerts.psize() = %d\n", (int)localGidVerts.psize());
> +  dbgOut.tprintf(1, "   localGidVerts.size() = %d\n", (int)localGidVerts.size());
> +
> +  // Create local vertices
> +  std::vector<double*> arrays;
> +  ErrorCode rval = _readNC->readMeshIface->get_node_coords(3, nLocalVertices, 0, start_vertex, arrays,
> +                                                          // Might have to create gather mesh later
> +                                                          (createGatherSet ? nLocalVertices + nVertices : nLocalVertices));
> +  ERRORR(rval, "Failed to create local vertices.");
> +
> +  // Add local vertices to the file set
> +  Range local_verts_range(start_vertex, start_vertex + nLocalVertices - 1);
> +  rval = _readNC->mbImpl->add_entities(_fileSet, local_verts_range);
> +  ERRORR(rval, "Failed to add local vertices to the file set.");
> +
> +  // Get ptr to GID memory for local vertices
> +  int count = 0;
> +  void* data = NULL;
> +  rval = mbImpl->tag_iterate(mGlobalIdTag, local_verts_range.begin(), local_verts_range.end(), count, data);
> +  ERRORR(rval, "Failed to iterate global id tag on local vertices.");
> +  assert(count == nLocalVertices);
> +  int* gid_data = (int*) data;
> +  std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
> +
> +  // Duplicate GID data, which will be used to resolve sharing
> +  if (mpFileIdTag) {
> +    rval = mbImpl->tag_iterate(*mpFileIdTag, local_verts_range.begin(), local_verts_range.end(), count, data);
> +    ERRORR(rval, "Failed to iterate file id tag on local vertices.");
> +    assert(count == nLocalVertices);
> +    gid_data = (int*) data;
> +    std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  size_t nb_reads = localGidVerts.psize();
> +  std::vector<int> requests(nb_reads);
> +  std::vector<int> statuss(nb_reads);
> +  size_t idxReq = 0;
> +#endif
> +
> +  // Read x coordinates for local vertices
> +  double* xptr = arrays[0];
> +  int xVertexVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "xVertex", &xVertexVarId);
> +  ERRORS(success, "Failed to get variable id of xVertex.");
> +  size_t indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
> +       pair_iter != localGidVerts.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_start = (NCDF_SIZE) (starth - 1);
> +    NCDF_SIZE read_count = (NCDF_SIZE) (endh - starth + 1);
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_double)(_fileId, xVertexVarId, &read_start, &read_count,
> +                                      &(xptr[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_double)(_fileId, xVertexVarId, &read_start, &read_count,
> +                                      &(xptr[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read xVertex data in a loop");
> +
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1);
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
> +
> +  // Read y coordinates for local vertices
> +  double* yptr = arrays[1];
> +  int yVertexVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "yVertex", &yVertexVarId);
> +  ERRORS(success, "Failed to get variable id of yVertex.");
> +#ifdef PNETCDF_FILE
> +  idxReq = 0;
> +#endif
> +  indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
> +       pair_iter != localGidVerts.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_start = (NCDF_SIZE) (starth - 1);
> +    NCDF_SIZE read_count = (NCDF_SIZE) (endh - starth + 1);
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_double)(_fileId, yVertexVarId, &read_start, &read_count,
> +                                      &(yptr[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_double)(_fileId, yVertexVarId, &read_start, &read_count,
> +                                      &(yptr[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read yVertex data in a loop");
> +
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1);
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
> +
> +  // Read z coordinates for local vertices
> +  double* zptr = arrays[2];
> +  int zVertexVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "zVertex", &zVertexVarId);
> +  ERRORS(success, "Failed to get variable id of zVertex.");
> +#ifdef PNETCDF_FILE
> +  idxReq = 0;
> +#endif
> +  indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
> +       pair_iter != localGidVerts.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_start = (NCDF_SIZE) (starth - 1);
> +    NCDF_SIZE read_count = (NCDF_SIZE) (endh - starth + 1);
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_double)(_fileId, zVertexVarId, &read_start, &read_count,
> +                                      &(zptr[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_double)(_fileId, zVertexVarId, &read_start, &read_count,
> +                                      &(zptr[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read zVertex data in a loop");
> +
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1);
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +  DebugOutput& dbgOut = _readNC->dbgOut;
> +
> +  // Read edges on each local cell, to get localGidEdges
> +  int edgesOnCellVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "edgesOnCell", &edgesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of edgesOnCell.");
> +
> +  std::vector<int> edges_on_local_cells(nLocalCells * maxEdgesPerCell);
> +  dbgOut.tprintf(1, "   edges_on_local_cells.size() = %d\n", (int)edges_on_local_cells.size());
> +
> +#ifdef PNETCDF_FILE
> +  size_t nb_reads = localGidCells.psize();
> +  std::vector<int> requests(nb_reads);
> +  std::vector<int> statuss(nb_reads);
> +  size_t idxReq = 0;
> +#endif
> +  size_t indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidCells.pair_begin();
> +       pair_iter != localGidCells.pair_end();
> +       pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_starts[2] = {static_cast<NCDF_SIZE>(starth - 1), 0};
> +    NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(endh - starth + 1), static_cast<NCDF_SIZE>(maxEdgesPerCell)};
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_int)(_fileId, edgesOnCellVarId, read_starts, read_counts,
> +                                      &(edges_on_local_cells[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_int)(_fileId, edgesOnCellVarId, read_starts, read_counts,
> +                                      &(edges_on_local_cells[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read edgesOnCell data in a loop");
> +
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1) * maxEdgesPerCell;
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
> +
> +  // Collect local edges
> +  std::sort(edges_on_local_cells.begin(), edges_on_local_cells.end());
> +  std::copy(edges_on_local_cells.rbegin(), edges_on_local_cells.rend(), range_inserter(localGidEdges));
> +  nLocalEdges = localGidEdges.size();
> +
> +  dbgOut.tprintf(1, "   localGidEdges.psize() = %d\n", (int)localGidEdges.psize());
> +  dbgOut.tprintf(1, "   localGidEdges.size() = %d\n", (int)localGidEdges.size());
> +
> +  // Create local edges
> +  EntityHandle start_edge;
> +  EntityHandle* conn_arr_edges = NULL;
> +  ErrorCode rval = _readNC->readMeshIface->get_element_connect(nLocalEdges, 2, MBEDGE, 0, start_edge, conn_arr_edges,
> +                                                    // Might have to create gather mesh later
> +                                                    (createGatherSet ? nLocalEdges + nEdges : nLocalEdges));
> +  ERRORR(rval, "Failed to create edges.");
> +
> +  // Add local edges to the file set
> +  Range local_edges_range(start_edge, start_edge + nLocalEdges - 1);
> +  rval = _readNC->mbImpl->add_entities(_fileSet, local_edges_range);
> +  ERRORR(rval, "Failed to add local edges to the file set.");
> +
> +  // Get ptr to GID memory for edges
> +  int count = 0;
> +  void* data = NULL;
> +  rval = mbImpl->tag_iterate(mGlobalIdTag, local_edges_range.begin(), local_edges_range.end(), count, data);
> +  ERRORR(rval, "Failed to iterate global id tag on local edges.");
> +  assert(count == nLocalEdges);
> +  int* gid_data = (int*) data;
> +  std::copy(localGidEdges.begin(), localGidEdges.end(), gid_data);
> +
> +  int verticesOnEdgeVarId;
> +
> +  // Read vertices on each local edge, to get edge connectivity
> +  // Utilize the memory storage pointed by conn_arr_edges
> +  success = NCFUNC(inq_varid)(_fileId, "verticesOnEdge", &verticesOnEdgeVarId);
> +  ERRORS(success, "Failed to get variable id of verticesOnEdge.");
> +  int* vertices_on_local_edges = (int*) conn_arr_edges;
> +#ifdef PNETCDF_FILE
> +  nb_reads = localGidEdges.psize();
> +  requests.resize(nb_reads);
> +  statuss.resize(nb_reads);
> +  idxReq = 0;
> +#endif
> +  indexInArray = 0;
> +  for (Range::pair_iterator pair_iter = localGidEdges.pair_begin();
> +      pair_iter != localGidEdges.pair_end();
> +      pair_iter++) {
> +    EntityHandle starth = pair_iter->first;
> +    EntityHandle endh = pair_iter->second;
> +    NCDF_SIZE read_starts[2] = {static_cast<NCDF_SIZE>(starth - 1), 0};
> +    NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(endh - starth + 1), 2};
> +
> +    // Do a partial read in each subrange
> +#ifdef PNETCDF_FILE
> +    success = NCFUNCREQG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts,
> +                                    &(vertices_on_local_edges[indexInArray]), &requests[idxReq++]);
> +#else
> +    success = NCFUNCAG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts,
> +                                    &(vertices_on_local_edges[indexInArray]));
> +#endif
> +    ERRORS(success, "Failed to read verticesOnEdge data in a loop");
> +
> +    // Increment the index for next subrange
> +    indexInArray += (endh - starth + 1) * 2;
> +  }
> +
> +#ifdef PNETCDF_FILE
> +  // Wait outside the loop
> +  success = NCFUNC(wait_all)(_fileId, requests.size(), &requests[0], &statuss[0]);
> +  ERRORS(success, "Failed on wait_all.");
> +#endif
> +
> +  // Populate connectivity for local edges
> +  // Convert in-place from int to EntityHandle type (backward)
> +  for (int edge_vert = nLocalEdges * 2 - 1; edge_vert >= 0; edge_vert--) {
> +    EntityHandle global_vert_id = vertices_on_local_edges[edge_vert]; // 1 based
> +    int vert_idx = localGidVerts.index(global_vert_id); // 0 based
> +    assert(vert_idx != -1);
> +    conn_arr_edges[edge_vert] = start_vertex + vert_idx;
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_local_cells,
> +                                                    const std::vector<int>& num_edges_on_local_cells,
> +                                                    EntityHandle start_vertex, Range& faces)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +
> +  // Divide local cells into groups based on the number of edges
> +  Range local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
> +  for (int i = nLocalCells - 1; i >= 0; i--) {
> +    int num_edges = num_edges_on_local_cells[i];
> +    local_cells_with_n_edges[num_edges].insert(localGidCells[i]); // Global cell index
> +  }
> +
> +  std::vector<int> num_edges_on_cell_groups;
> +  for (int i = 3; i <= maxEdgesPerCell; i++) {
> +    if (local_cells_with_n_edges[i].size() > 0)
> +      num_edges_on_cell_groups.push_back(i);
> +  }
> +  numCellGroups = num_edges_on_cell_groups.size();
> +
> +  EntityHandle* conn_arr_local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
> +  for (int i = 0; i < numCellGroups; i++) {
> +    int num_edges_per_cell = num_edges_on_cell_groups[i];
> +    int num_group_cells = (int)local_cells_with_n_edges[num_edges_per_cell].size();
> +
> +    // Create local cells for each non-empty cell group
> +    EntityHandle start_element;
> +    ErrorCode rval = _readNC->readMeshIface->get_element_connect(num_group_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
> +                                                       conn_arr_local_cells_with_n_edges[num_edges_per_cell], num_group_cells);
> +    ERRORR(rval, "Failed to create cells");
> +    faces.insert(start_element, start_element + num_group_cells - 1);
> +
> +    // Add local cells to the file set
> +    Range local_cells_range(start_element, start_element + num_group_cells - 1);
> +    rval = _readNC->mbImpl->add_entities(_fileSet, local_cells_range);
> +    ERRORR(rval, "Failed to add local cells to the file set.");
> +
> +    // Get ptr to gid memory for local cells
> +    int count = 0;
> +    void* data = NULL;
> +    rval = mbImpl->tag_iterate(mGlobalIdTag, local_cells_range.begin(), local_cells_range.end(), count, data);
> +    ERRORR(rval, "Failed to iterate global id tag on local cells.");
> +    assert(count == num_group_cells);
> +    int* gid_data = (int*) data;
> +    std::copy(local_cells_with_n_edges[num_edges_per_cell].begin(), local_cells_with_n_edges[num_edges_per_cell].end(), gid_data);
> +
> +    // Set connectivity array with proper local vertices handles
> +    for (int j = 0; j < num_group_cells; j++) {
> +      int cell_idx = (int)local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index
> +
> +      if (numCellGroups > 1)
> +        cellHandleToGlobalID[start_element + j] = cell_idx;
> +
> +      cell_idx = localGidCells.index(cell_idx);
> +      assert(cell_idx != -1);
> +
> +      for (int k = 0; k < num_edges_per_cell; k++) {
> +        EntityHandle global_vert_id = vertices_on_local_cells[cell_idx * maxEdgesPerCell + k];
> +        int idx_vertex = localGidVerts.index(global_vert_id);
> +        assert(idx_vertex != -1);
> +        conn_arr_local_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
> +            start_vertex + idx_vertex;
> +      }
> +    }
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_padded_local_cells(const std::vector<int>& vertices_on_local_cells,
> +                                                  const std::vector<int>& num_edges_on_local_cells,
> +                                                  EntityHandle start_vertex, Range& faces)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +
> +  // Only one group of cells (each cell is represented by a polygon with maxEdgesPerCell edges)
> +  numCellGroups = 1;
> +
> +  // Create cells for this cell group
> +  EntityHandle start_element;
> +  EntityHandle* conn_arr_local_cells = NULL;
> +  ErrorCode rval = _readNC->readMeshIface->get_element_connect(nLocalCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_local_cells,
> +                                                    // Might have to create gather mesh later
> +                                                    (createGatherSet ? nLocalCells + nCells : nLocalCells));
> +  ERRORR(rval, "Failed to create cells.");
> +  faces.insert(start_element, start_element + nLocalCells - 1);
> +
> +  // Add local cells to the file set
> +  Range local_cells_range(start_element, start_element + nLocalCells - 1);
> +  rval = _readNC->mbImpl->add_entities(_fileSet, local_cells_range);
> +  ERRORR(rval, "Failed to add local cells to the file set.");
> +
> +  // Get ptr to GID memory for local cells
> +  int count = 0;
> +  void* data = NULL;
> +  rval = mbImpl->tag_iterate(mGlobalIdTag, local_cells_range.begin(), local_cells_range.end(), count, data);
> +  ERRORR(rval, "Failed to iterate global id tag on local cells.");
> +  assert(count == nLocalCells);
> +  int* gid_data = (int*) data;
> +  std::copy(localGidCells.begin(), localGidCells.end(), gid_data);
> +
> +  // Set connectivity array with proper local vertices handles
> +  for (int cell_idx = 0; cell_idx < nLocalCells; cell_idx++) {
> +    int num_edges = num_edges_on_local_cells[cell_idx];
> +    for (int i = 0; i < num_edges; i++) {
> +      EntityHandle global_vert_id = vertices_on_local_cells[cell_idx * maxEdgesPerCell + i]; // 1 based
> +      int local_vert_idx = localGidVerts.index(global_vert_id); // 0 based
> +      assert(local_vert_idx != -1);
> +      conn_arr_local_cells[cell_idx * maxEdgesPerCell + i] = start_vertex + local_vert_idx;
> +    }
> +
> +    // Padding: fill connectivity array with last vertex handle
> +    if (num_edges < maxEdgesPerCell) {
> +      EntityHandle last_vert_id = conn_arr_local_cells[cell_idx * maxEdgesPerCell + num_edges - 1];
> +      for (int i = num_edges; i < maxEdgesPerCell; i++)
> +        conn_arr_local_cells[cell_idx * maxEdgesPerCell + i] = last_vert_id;
> +    }
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_gather_set_vertices(EntityHandle gather_set, EntityHandle& gather_set_start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +  Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
> +  const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
> +
> +  // Create gather set vertices
> +  std::vector<double*> arrays;
> +  // Don't need to specify allocation number here, because we know enough vertices were created before
> +  ErrorCode rval = _readNC->readMeshIface->get_node_coords(3, nVertices, 0, gather_set_start_vertex, arrays);
> +  ERRORR(rval, "Failed to create vertices.");
> +
> +  // Add vertices to the gather set
> +  Range gather_set_verts_range(gather_set_start_vertex, gather_set_start_vertex + nVertices - 1);
> +  rval = mbImpl->add_entities(gather_set, gather_set_verts_range);
> +  ERRORR(rval, "Failed to add vertices to the gather set.");
> +
> +  // Read x coordinates for gather set vertices
> +  double* xptr = arrays[0];
> +  int xVertexVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "xVertex", &xVertexVarId);
> +  ERRORS(success, "Failed to get variable id of xVertex.");
> +  NCDF_SIZE read_start = 0;
> +  NCDF_SIZE read_count = static_cast<NCDF_SIZE>(nVertices);
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_double)(_fileId, xVertexVarId, &read_start, &read_count, xptr);
> +  ERRORS(success, "Failed to read xVertex data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_double)(_fileId, xVertexVarId, &read_start, &read_count, xptr);
> +  ERRORS(success, "Failed to read xVertex data.");
> +#endif
> +
> +  // Read y coordinates for gather set vertices
> +  double* yptr = arrays[1];
> +  int yVertexVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "yVertex", &yVertexVarId);
> +  ERRORS(success, "Failed to get variable id of yVertex.");
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_double)(_fileId, yVertexVarId, &read_start, &read_count, yptr);
> +  ERRORS(success, "Failed to read yVertex data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_double)(_fileId, yVertexVarId, &read_start, &read_count, yptr);
> +  ERRORS(success, "Failed to read yVertex data.");
> +#endif
> +
> +  // Read z coordinates for gather set vertices
> +  double* zptr = arrays[2];
> +  int zVertexVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "zVertex", &zVertexVarId);
> +  ERRORS(success, "Failed to get variable id of zVertex.");
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_double)(_fileId, zVertexVarId, &read_start, &read_count, zptr);
> +  ERRORS(success, "Failed to read zVertex data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_double)(_fileId, zVertexVarId, &read_start, &read_count, zptr);
> +  ERRORS(success, "Failed to read zVertex data.");
> +#endif
> +
> +  // Get ptr to GID memory for gather set vertices
> +  int count = 0;
> +  void* data = NULL;
> +  rval = mbImpl->tag_iterate(mGlobalIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count, data);
> +  ERRORR(rval, "Failed to iterate global id tag on gather set vertices.");
> +  assert(count == nVertices);
> +  int* gid_data = (int*) data;
> +  for (int j = 1; j <= nVertices; j++)
> +    gid_data[j - 1] = j;
> +
> +  // Set the file id tag too, it should be bigger something not interfering with global id
> +  if (mpFileIdTag) {
> +    rval = mbImpl->tag_iterate(*mpFileIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count, data);
> +    ERRORR(rval, "Failed to iterate file id tag on gather set vertices.");
> +    assert(count == nVertices);
> +    gid_data = (int*) data;
> +    for (int j = 1; j <= nVertices; j++)
> +      gid_data[j - 1] = nVertices + j; // Bigger than global id tag
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_gather_set_edges(EntityHandle gather_set, EntityHandle gather_set_start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +
> +  // Create gather set edges
> +  EntityHandle start_edge;
> +  EntityHandle* conn_arr_gather_edges = NULL;
> +  // Don't need to specify allocation number here, because we know enough edges were created before
> +  ErrorCode rval = _readNC->readMeshIface->get_element_connect(nEdges, 2, MBEDGE, 0, start_edge, conn_arr_gather_edges);
> +  ERRORR(rval, "Failed to create edges.");
> +
> +  // Add edges to the gather set
> +  Range gather_edges_range(start_edge, start_edge + nEdges - 1);
> +  rval = mbImpl->add_entities(gather_set, gather_edges_range);
> +  ERRORR(rval, "Failed to add edges to the gather set.");
> +
> +  // Read vertices on each edge
> +  int verticesOnEdgeVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "verticesOnEdge", &verticesOnEdgeVarId);
> +  ERRORS(success, "Failed to get variable id of verticesOnEdge.");
> +  std::vector<int> vertices_on_gather_edges(nEdges * 2);
> +  NCDF_SIZE read_starts[2] = {0, 0};
> +  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nEdges), 2};
> + #ifdef PNETCDF_FILE
> +   // Enter independent I/O mode, since this read is only for the gather processor
> +   success = NCFUNC(begin_indep_data)(_fileId);
> +   ERRORS(success, "Failed to begin independent I/O mode.");
> +   success = NCFUNCG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts, &vertices_on_gather_edges[0]);
> +   ERRORS(success, "Failed to read verticesOnEdge data.");
> +   success = NCFUNC(end_indep_data)(_fileId);
> +   ERRORS(success, "Failed to end independent I/O mode.");
> + #else
> +   success = NCFUNCG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts, &vertices_on_gather_edges[0]);
> +   ERRORS(success, "Failed to read verticesOnEdge data.");
> + #endif
> +
> +   std::copy(vertices_on_gather_edges.begin(), vertices_on_gather_edges.end(), conn_arr_gather_edges);
> +   for (int i = 0; i < 2 * nEdges; i++)
> +     // Connectivity array is shifted by where the gather set vertices start
> +     conn_arr_gather_edges[i] += gather_set_start_vertex - 1;
> +
> +   return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_gather_set_cells(EntityHandle gather_set, EntityHandle gather_set_start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +
> +  // Read number of edges on each gather set cell
> +  int nEdgesOnCellVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "nEdgesOnCell", &nEdgesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of nEdgesOnCell.");
> +  std::vector<int> num_edges_on_gather_cells(nCells);
> +  NCDF_SIZE read_start = 0;
> +  NCDF_SIZE read_count = static_cast<NCDF_SIZE>(nCells);
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read nEdgesOnCell data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read nEdgesOnCell data.");
> +#endif
> +
> +  // Read vertices on each gather set cell (connectivity)
> +  int verticesOnCellVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of verticesOnCell.");
> +  std::vector<int> vertices_on_gather_cells(nCells * maxEdgesPerCell);
> +  NCDF_SIZE read_starts[2] = {0, 0};
> +  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), maxEdgesPerCell};
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read verticesOnCell data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read verticesOnCell data.");
> +#endif
> +
> +  // Divide gather set cells into groups based on the number of edges
> +  std::vector<int> gather_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
> +  for (int i = 0; i < nCells; i++) {
> +    int num_edges = num_edges_on_gather_cells[i];
> +    gather_cells_with_n_edges[num_edges].push_back(i + 1); // 0 based -> 1 based
> +  }
> +
> +  // Create gather set cells
> +  EntityHandle* conn_arr_gather_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
> +  for (int num_edges_per_cell = 3; num_edges_per_cell <= maxEdgesPerCell; num_edges_per_cell++) {
> +    int num_group_cells = gather_cells_with_n_edges[num_edges_per_cell].size();
> +    if (num_group_cells > 0) {
> +      EntityHandle start_element;
> +      ErrorCode rval = _readNC->readMeshIface->get_element_connect(num_group_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
> +                                                         conn_arr_gather_cells_with_n_edges[num_edges_per_cell], num_group_cells);
> +      ERRORR(rval, "Failed to create cells.");
> +
> +      // Add cells to the gather set
> +      Range gather_cells_range(start_element, start_element + num_group_cells - 1);
> +      rval = mbImpl->add_entities(gather_set, gather_cells_range);
> +      ERRORR(rval, "Failed to add cells to the gather set.");
> +
> +      for (int j = 0; j < num_group_cells; j++) {
> +        int cell_idx = gather_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index
> +        cell_idx--; // 1 based -> 0 based
> +
> +        for (int k = 0; k < num_edges_per_cell; k++)
> +          // Connectivity array is shifted by where the gather set vertices start
> +          conn_arr_gather_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
> +            (gather_set_start_vertex - 1) + vertices_on_gather_cells[cell_idx * maxEdgesPerCell + k];
> +      }
> +    }
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
> +ErrorCode NCHelperMPAS::create_padded_gather_set_cells(EntityHandle gather_set, EntityHandle gather_set_start_vertex)
> +{
> +  Interface*& mbImpl = _readNC->mbImpl;
> +
> +  // Read number of edges on each gather set cell
> +  int nEdgesOnCellVarId;
> +  int success = NCFUNC(inq_varid)(_fileId, "nEdgesOnCell", &nEdgesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of nEdgesOnCell.");
> +  std::vector<int> num_edges_on_gather_cells(nCells);
> +  NCDF_SIZE read_start = 0;
> +  NCDF_SIZE read_count = static_cast<NCDF_SIZE>(nCells);
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read nEdgesOnCell data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read nEdgesOnCell data.");
> +#endif
> +
> +  // Read vertices on each gather set cell (connectivity)
> +  int verticesOnCellVarId;
> +  success = NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCellVarId);
> +  ERRORS(success, "Failed to get variable id of verticesOnCell.");
> +  std::vector<int> vertices_on_gather_cells(nCells * maxEdgesPerCell);
> +  NCDF_SIZE read_starts[2] = {0, 0};
> +  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), maxEdgesPerCell};
> +#ifdef PNETCDF_FILE
> +  // Enter independent I/O mode, since this read is only for the gather processor
> +  success = NCFUNC(begin_indep_data)(_fileId);
> +  ERRORS(success, "Failed to begin independent I/O mode.");
> +  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read verticesOnCell data.");
> +  success = NCFUNC(end_indep_data)(_fileId);
> +  ERRORS(success, "Failed to end independent I/O mode.");
> +#else
> +  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_cells[0]);
> +  ERRORS(success, "Failed to read verticesOnCell data.");
> +#endif
> +
> +  // Create gather set cells
> +  EntityHandle start_element;
> +  EntityHandle* conn_arr_gather_cells = NULL;
> +  // Don't need to specify allocation number here, because we know enough cells were created before
> +  ErrorCode rval = _readNC->readMeshIface->get_element_connect(nCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_gather_cells);
> +  ERRORR(rval, "Failed to create cells.");
> +
> +  // Add cells to the gather set
> +  Range gather_cells_range(start_element, start_element + nCells - 1);
> +  rval = mbImpl->add_entities(gather_set, gather_cells_range);
> +  ERRORR(rval, "Failed to add cells to the gather set.");
> +
> +  for (int cell_idx = 0; cell_idx < nCells; cell_idx++) {
> +    int num_edges = num_edges_on_gather_cells[cell_idx];
> +    for (int i = 0; i < num_edges; i++)
> +      // Connectivity array is shifted by where the gather set vertices start
> +      conn_arr_gather_cells[cell_idx * maxEdgesPerCell + i] = (gather_set_start_vertex - 1) + vertices_on_gather_cells[cell_idx * maxEdgesPerCell + i];
> +
> +    // Padding: fill connectivity array with last vertex handle
> +    EntityHandle last_vert_id = conn_arr_gather_cells[cell_idx * maxEdgesPerCell + num_edges - 1];
> +    for (int i = num_edges; i < maxEdgesPerCell; i++)
> +      conn_arr_gather_cells[cell_idx * maxEdgesPerCell + i] = last_vert_id;
> +  }
> +
> +  return MB_SUCCESS;
> +}
> +
>  } // namespace moab
>
> diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
> index 789a0fb..5c751a0 100644
> --- a/src/io/NCHelperMPAS.hpp
> +++ b/src/io/NCHelperMPAS.hpp
> @@ -26,7 +26,7 @@ private:
>    //! Implementation of NCHelper::check_existing_mesh()
>    virtual ErrorCode check_existing_mesh();
>    //! Implementation of NCHelper::create_mesh()
> -  virtual ErrorCode create_mesh(Range& quads);
> +  virtual ErrorCode create_mesh(Range& faces);
>    //! Implementation of NCHelper::get_mesh_type_name()
>    virtual std::string get_mesh_type_name() { return "MPAS"; }
>
> @@ -48,10 +48,41 @@ private:
>                                                  std::vector<int>& tstep_nums);
>  #endif
>
> +  //! Redistribute local cells after trivial partition (e.g. Zoltan partition, if applicable)
> +  ErrorCode redistribute_local_cells(int start_cell_index);
> +
> +  //! Create local vertices
> +  ErrorCode create_local_vertices(const std::vector<int>& vertices_on_local_cells, EntityHandle& start_vertex);
> +
> +  //! Create local edges (optional)
> +  ErrorCode create_local_edges(EntityHandle start_vertex);
> +
> +  //! Create local cells without padding (cells are divided into groups based on the number of edges)
> +  ErrorCode create_local_cells(const std::vector<int>& vertices_on_local_cells,
> +                                        const std::vector<int>& num_edges_on_local_cells,
> +                                        EntityHandle start_vertex, Range& faces);
> +
> +  //! Create local cells with padding (padded cells will have the same number of edges)
> +  ErrorCode create_padded_local_cells(const std::vector<int>& vertices_on_local_cells,
> +                                      const std::vector<int>& num_edges_on_local_cells,
> +                                      EntityHandle start_vertex, Range& faces);
> +
> +  //! Create gather set vertices
> +  ErrorCode create_gather_set_vertices(EntityHandle gather_set, EntityHandle& gather_set_start_vertex);
> +
> +  //! Create gather set edges (optional)
> +  ErrorCode create_gather_set_edges(EntityHandle gather_set, EntityHandle gather_set_start_vertex);
> +
> +  //! Create gather set cells without padding (cells are divided into groups based on the number of edges)
> +  ErrorCode create_gather_set_cells(EntityHandle gather_set, EntityHandle gather_set_start_vertex);
> +
> +  //! Create gather set cells with padding (padded cells will have the same number of edges)
> +  ErrorCode create_padded_gather_set_cells(EntityHandle gather_set, EntityHandle gather_set_start_vertex);
> +
>  private:
> -  int maxCellEdges;
> +  int maxEdgesPerCell;
>    int numCellGroups;
> -  std::vector<int> verticesOnEdge;
> +  bool createGatherSet;
>    std::map<EntityHandle, int> cellHandleToGlobalID;
>    Range facesOwned;
>  };
>
> diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
> index a27a89d..e930930 100644
> --- a/src/io/ReadNC.cpp
> +++ b/src/io/ReadNC.cpp
> @@ -19,12 +19,13 @@ ReaderIface* ReadNC::factory(Interface* iface)
>  }
>
>  ReadNC::ReadNC(Interface* impl) :
> -        mbImpl(impl), fileId(-1), mGlobalIdTag(0), mpFileIdTag(NULL), dbgOut(stderr), isParallel(false),
> -        partMethod(ScdParData::ALLJORKORI), scdi(NULL),
> +  mbImpl(impl), fileId(-1), mGlobalIdTag(0), mpFileIdTag(NULL), dbgOut(stderr), isParallel(false),
> +  partMethod(ScdParData::ALLJORKORI), scdi(NULL),
>  #ifdef USE_MPI
>    myPcomm(NULL),
>  #endif
> -  noMesh(false), noVars(false), spectralMesh(false), gatherSetRank(-1), myHelper(NULL)
> +  noMesh(false), noVars(false), spectralMesh(false), noMixedElements(false), noEdges(false),
> +  gatherSetRank(-1), myHelper(NULL)
>  {
>    assert(impl != NULL);
>    impl->query_interface(readMeshIface);
> @@ -214,6 +215,14 @@ ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string
>    if (MB_SUCCESS == rval)
>      spectralMesh = true;
>
> +  rval = opts.get_null_option("NO_MIXED_ELEMENTS");
> +  if (MB_SUCCESS == rval)
> +    noMixedElements = true;
> +
> +  rval = opts.get_null_option("NO_EDGES");
> +  if (MB_SUCCESS == rval)
> +    noEdges = true;
> +
>    if (2 <= dbgOut.get_verbosity()) {
>      if (!var_names.empty()) {
>        std::cerr << "Variables requested: ";
>
> diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
> index e8b1845..fc75140 100644
> --- a/src/io/ReadNC.hpp
> +++ b/src/io/ReadNC.hpp
> @@ -207,6 +207,8 @@ private:
>    bool noMesh;
>    bool noVars;
>    bool spectralMesh;
> +  bool noMixedElements;
> +  bool noEdges;
>    int gatherSetRank;
>
>    //! Helper class instance
>
> diff --git a/src/io/mhdf/example/validate.c b/src/io/mhdf/example/validate.c
> index 3ed7e78..4bd3ad8 100644
> --- a/src/io/mhdf/example/validate.c
> +++ b/src/io/mhdf/example/validate.c
> @@ -816,12 +816,13 @@ static int merge_ranges( long* ranges, int nranges )
>    qsort( ranges, nranges, 2*sizeof(long), &lcomp );
>    n = 1;
>    for (i = 1; i < nranges; ++i) {
> -    if (ranges[2*n-2] + ranges[2*n-1+1] == ranges[2*i]) {
> -      ranges[2*n-1] += ranges[2*i+1];
> +    if (ranges[2*n-2] + ranges[2*n-1] == ranges[2*i]) {
> +      ranges[2*n-1] += ranges[2*i+1]; /*compact the range*/
>      }
>      else {
> -      ranges[2*n  ] = ranges[i];
> -      ranges[2*n+1] = ranges[i+1];
> +      /* do not compact, just copy, and increase number of ranges*/
> +      ranges[2*n  ] = ranges[2*i];
> +      ranges[2*n+1] = ranges[2*i+1];
>        ++n;
>      }
>    }
>
> diff --git a/src/moab/ScdInterface.hpp b/src/moab/ScdInterface.hpp
> index 0726b13..1f2a482 100644
> --- a/src/moab/ScdInterface.hpp
> +++ b/src/moab/ScdInterface.hpp
> @@ -112,7 +112,7 @@ public:
>      //! Partition method enumeration; these strategies are described in comments for
>      //! compute_partition_alljorkori, compute_partition_alljkbal, compute_partition_sqij,
>      //! compute_partition_sqjk, and compute_partition_sqijk
> -  enum PartitionMethod {ALLJORKORI = 0, ALLJKBAL, SQIJ, SQJK, SQIJK, TRIVIAL, NOPART};
> +  enum PartitionMethod {ALLJORKORI = 0, ALLJKBAL, SQIJ, SQJK, SQIJK, TRIVIAL, RCBZOLTAN, NOPART};
>
>      //! Partition method names
>    static const char *PartitionMethodNames[NOPART + 1];
>
> This diff is so big that we needed to truncate the remainder.
>
> https://bitbucket.org/fathomteam/moab/commits/f7edd757ad49/
> Changeset:   f7edd757ad49
> Branch:      None
> User:        Vijay S Mahadevan
> Date:        2013-12-04 23:09:53
> Summary:     Merge branch 'master' of https://bitbucket.org/vijaysm/moab
>
> Affected #:  0 files
>
>
>
> https://bitbucket.org/fathomteam/moab/commits/bc4d2aeae8fd/
> Changeset:   bc4d2aeae8fd
> Branch:      None
> User:        Vijay S Mahadevan
> Date:        2014-01-08 22:24:43
> Summary:     Merge branch 'master' of bitbucket.org:vijaysm/moab
>
> Affected #:  0 files
>
>
>
> https://bitbucket.org/fathomteam/moab/commits/e9ed5141a0dd/
> Changeset:   e9ed5141a0dd
> Branch:      None
> User:        Vijay Mahadevan
> Date:        2014-01-09 02:32:00
> Summary:     Fixing the CMake build system to configure correctly with the latest source branch. Tests are not working correctly still.
>
> Affected #:  6 files
>
> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
> index 280b203..40f7a59 100644
> --- a/src/CMakeLists.txt
> +++ b/src/CMakeLists.txt
> @@ -7,6 +7,7 @@
>      AxisBox.cpp
>      BitPage.cpp
>      BitTag.cpp
> +    BoundBox.cpp
>      BSPTree.cpp
>      BSPTreePoly.cpp
>      CN.cpp
> @@ -46,6 +47,8 @@
>      SweptVertexData.cpp
>      SysUtil.cpp
>      TagInfo.cpp
> +    Tree.cpp
> +    TupleList.cpp
>      Types.cpp
>      TypeSequenceManager.cpp
>      UnstructuredElemSeq.cpp
> @@ -93,14 +96,27 @@
>      io/WriteVtk.cpp
>      ReaderWriterSet.cpp
>    )
> +
> +  set ( MOABLD_LIB_SRCS
> +    LocalDiscretization/ElemEvaluator.cpp
> +    LocalDiscretization/LinearHex.cpp
> +    LocalDiscretization/LinearQuad.cpp
> +    LocalDiscretization/LinearTet.cpp
> +    LocalDiscretization/LinearTri.cpp
> +    LocalDiscretization/QuadraticHex.cpp
> +#    LocalDiscretization/SpectralHex.cpp
> +#    LocalDiscretization/SpectralQuad.cpp
> +  )
> +
>    include_directories(
> -    ${MOAB_BINARY_DIR}
>      ${MOAB_SOURCE_DIR}/src
> -    ${MOAB_BINARY_DIR}/src
>      ${MOAB_SOURCE_DIR}/src/io
>      ${MOAB_SOURCE_DIR}/src/parallel
> -    ${MOAB_BINARY_DIR}/src/parallel
> +    ${MOAB_SOURCE_DIR}/src/LocalDiscretization
>      ${MOAB_SOURCE_DIR}/src/moab/point_locater/lotte
> +    ${MOAB_BINARY_DIR}
> +    ${MOAB_BINARY_DIR}/src
> +    ${MOAB_BINARY_DIR}/src/parallel
>    )
>
>    if ( NetCDF_FOUND )
> @@ -143,7 +159,7 @@
>    endif ( HDF5_FOUND )
>
>
> -  SET(MOAB_LIB_SRCS ${MOABCORE_LIB_SRCS} ${MOABPTLOC_LIB_SRCS} ${MOABIO_LIB_SRCS})
> +  SET(MOAB_LIB_SRCS ${MOABCORE_LIB_SRCS} ${MOABPTLOC_LIB_SRCS} ${MOABIO_LIB_SRCS} ${MOABLD_LIB_SRCS})
>
>    set_source_files_properties( ${MOAB_LIB_SRCS}
>      COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}"
>
> diff --git a/src/parallel/CMakeLists.txt b/src/parallel/CMakeLists.txt
> index 7583885..9021ee2 100644
> --- a/src/parallel/CMakeLists.txt
> +++ b/src/parallel/CMakeLists.txt
> @@ -4,7 +4,6 @@ set( moab_PARALLEL_SRCS
>    ParallelData.cpp
>    ReadParallel.cpp
>    gs.cpp
> -  TupleList.cpp
>    SharedSetData.cpp
>  )
>
>
> diff --git a/test/parallel/mhdf_parallel.c b/test/parallel/mhdf_parallel.c
> index 848619b..178d183 100644
> --- a/test/parallel/mhdf_parallel.c
> +++ b/test/parallel/mhdf_parallel.c
> @@ -26,6 +26,8 @@
>  #include <H5FDmpi.h>
>  #include <H5FDmpio.h>
>
> +#ifdef H5_HAVE_PARALLEL
> +
>  const char filename[] = "mhdf_ll.h5m";
>  const char proc_tag_name[] = "proc_id";
>  const char elem_handle[] = "Hex";
> @@ -280,9 +282,12 @@ static herr_t handle_hdf5_error( void* data )
>    assert(0);
>    return result;
>  }
> +
> +#endif // #ifdef H5_HAVE_PARALLEL
>
>  int main( int argc, char* argv[] )
>  {
> +#ifdef H5_HAVE_PARALLEL
>    int rval;
>    void* data;
>    herr_t err;
> @@ -321,5 +326,6 @@ int main( int argc, char* argv[] )
>    write_file_data();
>
>    MPI_Finalize();
> +#endif
>    return 0;
>  }
>
> diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
> index fd85330..8e990a9 100644
> --- a/tools/CMakeLists.txt
> +++ b/tools/CMakeLists.txt
> @@ -105,11 +105,6 @@
>      add_subdirectory( qvdual )
>    endif ( MOAB_BUILD_QVDUAL )
>
> -  # CGM
> -  if ( MOAB_BUILD_DAGMC )
> -    add_subdirectory( dagmc )
> -  endif ( MOAB_BUILD_DAGMC )
> -
>    # MBCoupler
>    if ( MOAB_USE_MPI AND MPI_FOUND AND MOAB_BUILD_MBCOUPLER )
>  #  if ( MOAB_BUILD_MBCOUPLER )
>
> diff --git a/tools/dagmc/CMakeLists.txt b/tools/dagmc/CMakeLists.txt
> index 2326f55..14974cb 100644
> --- a/tools/dagmc/CMakeLists.txt
> +++ b/tools/dagmc/CMakeLists.txt
> @@ -2,12 +2,13 @@
>  find_package( CGM )
>
>  include_directories(
> -  ${CMAKE_CURRENT_BINARY_DIR}
> -  ${CMAKE_CURRENT_SOURCE_DIR}
> -  ${MOAB_BINARY_DIR}/src
> -  ${MOAB_SOURCE_DIR}/src
> +    ${CMAKE_CURRENT_SOURCE_DIR}
> +    ${MOAB_BINARY_DIR}
> +    ${MOAB_SOURCE_DIR}/src
> +    ${MOAB_BINARY_DIR}/src
>  )
>
> +
>  set( MOAB_DAGMC_LIB_SRCS
>    DagMC.cpp
>  )
>
> diff --git a/tools/mbcoupler/CMakeLists.txt b/tools/mbcoupler/CMakeLists.txt
> index da316c8..019f939 100644
> --- a/tools/mbcoupler/CMakeLists.txt
> +++ b/tools/mbcoupler/CMakeLists.txt
> @@ -16,7 +16,7 @@ set( MBCOUPLER_SRCS
>  )
>
>  set_source_files_properties( ${MBCOUPLER_SRCS}
> -  COMPILE_FLAGS "${MOAB_DEFINES}"
> +  COMPILE_FLAGS "${MOAB_DEFINES} -DIS_BUILDING_MB"
>  )
>
>  add_library( mbcoupler
> @@ -30,13 +30,6 @@ endif ( MOAB_USE_MPI )
>
>  enable_testing()
>
> -# A test for the coupler library
> -add_executable( findpt_test findpt_test.cpp )
> -target_link_libraries( findpt_test mbcoupler MOAB )
> -if ( MOAB_USE_MPI )
> -  target_link_libraries( findpt_test MOABpar )
> -endif ( MOAB_USE_MPI )
> -add_test( TestMBCouplerFindPt ${EXECUTABLE_OUTPUT_PATH}/findpt_test )
>
>  if ( MOAB_USE_MPI )
>    # Exercise the coupler and not just findpt:
>
>
> https://bitbucket.org/fathomteam/moab/commits/47bcc42c10a4/
> Changeset:   47bcc42c10a4
> Branch:      master
> User:        vijaysm
> Date:        2014-01-09 02:36:07
> Summary:     Merge branch 'master' of bitbucket.org:vijaysm/moab
>
> Affected #:  0 files
>
> Repository URL: https://bitbucket.org/fathomteam/moab/
>
> --
>
> This is a commit notification from bitbucket.org. You are receiving
> this because you have the service enabled, addressing the recipient of
> this email.


More information about the moab-dev mailing list