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

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Thu Jan 9 14:17:56 CST 2014


24 new commits in MOAB:

https://bitbucket.org/fathomteam/moab/commits/dca29ec70e88/
Changeset:   dca29ec70e88
Branch:      None
User:        danwu
Date:        2013-07-25 17:57:04
Summary:     Merged fathomteam/moab into master
Affected #:  2 files

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index 82c06e5..253440b 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -2033,7 +2033,10 @@ ErrorCode AdaptiveKDTree::ray_intersect_triangles( EntityHandle root,
               }
               tris_out[w] = *iter;
               dists_out[w] = tri_t;
-              ray_end = dists_out.back();
+              if (tris_out.size() >= (unsigned)max_ints)
+                // when we have already reached the max intx points, we cans safely reset
+                // ray_end, because we will accept new points only "closer" than the last one
+                ray_end = dists_out.back();
             }
           }
         }

diff --git a/tools/mbcslam/intx_mpas.cpp b/tools/mbcslam/intx_mpas.cpp
index 679bd03..ab50ce9 100644
--- a/tools/mbcslam/intx_mpas.cpp
+++ b/tools/mbcslam/intx_mpas.cpp
@@ -122,6 +122,7 @@ int main(int argc, char **argv)
   std::string extra_read_opts;
   std::string fileN= TestDir + "/mpas_p8.h5m";
   const char *filename_mesh1 = fileN.c_str();
+  bool flux_form = false;
   if (argc > 1)
   {
     int index = 1;
@@ -147,6 +148,11 @@ int main(int argc, char **argv)
       {
         extra_read_opts = std::string(argv[++index]);
       }
+      if (!strcmp(argv[index], "-FF"))
+      {
+        flux_form= true;
+        index++;
+      }
 
       index++;
     }
@@ -181,9 +187,12 @@ int main(int argc, char **argv)
     return 1;
   // create a set with quads corresponding to each initial edge spanned with the displacement field
 
-  rval = create_span_quads(&mb, euler_set, rank);
-  if (MB_SUCCESS != rval)
-    return 1;
+  if (flux_form)
+  {
+    rval = create_span_quads(&mb, euler_set, rank);
+    if (MB_SUCCESS != rval)
+      return 1;
+  }
 
   EntityHandle covering_lagr_set;
   rval = mb.create_meshset(MESHSET_SET, covering_lagr_set);


https://bitbucket.org/fathomteam/moab/commits/96d7fc626cba/
Changeset:   96d7fc626cba
Branch:      None
User:        danwu
Date:        2013-08-02 17:07:07
Summary:     Merged fathomteam/moab into master
Affected #:  34 files

diff --git a/MeshFiles/unittest/125hex.g b/MeshFiles/unittest/125hex.g
index 6cf0433..2042583 100644
Binary files a/MeshFiles/unittest/125hex.g and b/MeshFiles/unittest/125hex.g differ

diff --git a/MeshFiles/unittest/1hex.g b/MeshFiles/unittest/1hex.g
index 3dcd658..0affc6e 100644
Binary files a/MeshFiles/unittest/1hex.g and b/MeshFiles/unittest/1hex.g differ

diff --git a/MeshFiles/unittest/1khex.g b/MeshFiles/unittest/1khex.g
index e6c9417..6b0a8fc 100644
Binary files a/MeshFiles/unittest/1khex.g and b/MeshFiles/unittest/1khex.g differ

diff --git a/MeshFiles/unittest/64bricks_512hex_256part.h5m b/MeshFiles/unittest/64bricks_512hex_256part.h5m
new file mode 100644
index 0000000..d7df13c
Binary files /dev/null and b/MeshFiles/unittest/64bricks_512hex_256part.h5m differ

diff --git a/MeshFiles/unittest/surfrandomtris-4part.h5m b/MeshFiles/unittest/surfrandomtris-4part.h5m
new file mode 100644
index 0000000..1ca984a
Binary files /dev/null and b/MeshFiles/unittest/surfrandomtris-4part.h5m differ

diff --git a/configure.ac b/configure.ac
index 8a308cb..b08389a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -451,13 +451,18 @@ AC_SUBST(PNETCDF_LIBS)
 #                             Documentation
 #################################################################################
 AC_ARG_ENABLE([docs],
-[AC_HELP_STRING([--enable-docs],[Specify directory where Doxygen program is installed])
-AC_HELP_STRING([--disable-docs],[Do not generate API documentation (default)])],
-                        [ENABLE_DOCS="$enableval"],[ENABLE_DOCS=no] )
-if test "x$ENABLE_DOCS" != "xno"; then
-  AC_PATH_PROG( [DOXYGEN], [doxygen], [no] )
+[AC_HELP_STRING([--enable-docs],[indicate to check for doxygen installation])],
+                        [ENABLE_DOCS=yes],[ENABLE_DOCS=no] )
+AC_ARG_WITH([doxygen],
+[AC_HELP_STRING([--with-doxygen=DIR], [Specify directory where Doxygen program is installed. By default, it is /usr/bin])],
+[WITH_DOXYGEN="$withval"], [WITH_DOXYGEN=no])
+
+if test "x$WITH_DOXYGEN" != "xno"; then
+  AC_PATH_PROGS( [DOXYGEN], [doxygen], [no],[$WITH_DOXYGEN] )
+else
+  AC_PATH_PROGS( [DOXYGEN], [doxygen], [no],[$PATH])
 fi
-if test "x$ENABLE_DOCS" != "xno"; then
+if test "x$ENABLE_DOCS" = "xyes"; then
   if test "x$DOXYGEN" = "xno"; then
     AC_MSG_ERROR("Doxygen executable not found.")
   fi
@@ -1141,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 51281b1..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/MOAB-UG.doc b/doc/MOAB-UG.doc
index 281d619..5cf591c 100644
Binary files a/doc/MOAB-UG.doc and b/doc/MOAB-UG.doc differ

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/README b/doc/README
new file mode 100644
index 0000000..76ed8b5
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,21 @@
+How to generate doxygen document for MOAB in Linux:
+
+-  Install doxygen, and include the doxygen installation path to PATH.
+
+-  After checking out moab from bitbucket, do following under moab directory:
+
+   autoreconf -fi
+   ./configure [options] --enable-docs --with-doxygen=DIR
+   make
+   make check
+   cd doc
+   doxygen user.dox
+
+(--ebable-docs indicates to check for doxygen installation under your given --with-doxygen directory or, if --with-doxygen is not given, under your PATH. If doxygen execuable is not found, it'll report error and exit configure.
+
+If you are sure doxygen is installed and put into PATH, you don't need to add --enable-docs or --with-doxygen, going to doc directory and directly applying "doxygen user.dox" should generate all the documents.)
+
+-  After doxygen is done, you should be able to open web browser, and view MOAB document at file://your_moab_dir/doc/html/index.html . 
+
+
+

diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
index f3f186d..c5231fa 100644
--- a/doc/UG/moabUG.h
+++ b/doc/UG/moabUG.h
@@ -500,8 +500,8 @@ Applications calling the reader interface functions directly can specify the all
 
 The reader interface consists of the following functions:
 
-- get_node_arrays: Given the number of vertices requested, the number of geometric dimensions, and a requested start id, allocates a block of vertex handles and returns pointers to coordinate arrays in memory, along with the actual start handle for that block of vertices.
-- get_element_array: Given the number of elements requested, the number of vertices per element, the element type and the requested start id, allocates the block of elements, and returns a pointer to the connectivity array for those elements and the actual start handle for that block.  The number of vertices per element is necessary because those elements may include higher-order nodes, and MOAB stores these as part of the normal connectivity array.
+- get_node_coords: Given the number of vertices requested, the number of geometric dimensions, and a requested start id, allocates a block of vertex handles and returns pointers to coordinate arrays in memory, along with the actual start handle for that block of vertices.
+- get_element_connect: Given the number of elements requested, the number of vertices per element, the element type and the requested start id, allocates the block of elements, and returns a pointer to the connectivity array for those elements and the actual start handle for that block.  The number of vertices per element is necessary because those elements may include higher-order nodes, and MOAB stores these as part of the normal connectivity array.
 - update_adjacencies: This function takes the start handle for a block of elements and the connectivity of those elements, and updates adjacencies for those elements.  Which adjacencies are updated depends on the options set in AEntityFactory.
 .
 
@@ -515,12 +515,12 @@ ErrorCode rval = moab->get_interface("ReadUtilIface", &iface);
 // allocate a block of vertex handles and read xyz’s into them
 std::vector<double*> arrays;
 EntityHandle startv, *starth;
-rval = iface->get_node_arrays(3, num_nodes, 0, startv, arrays);
+rval = iface->get_node_coords(3, num_nodes, 0, startv, arrays);
 for (int i = 0; i < num_nodes; i++)
   infile >> arrays[0][i] >> arrays[1][i] >> arrays[2][i];
 
 // allocate block of hex handles and read connectivity into them
-rval = iface->get_element_array(num_hexes, 8, MBHEX, 0, starth);
+rval = iface->get_element_connect(num_hexes, 8, MBHEX, 0, starth);
 for (int i = 0; i < 8*num_hexes; i++)
   infile >> starth[i];
 
@@ -531,8 +531,8 @@ for (int i = 0; i < 8*num_hexes; i++)
 
 The writer interface, declared in WriteUtilIface, provides functions that support writing vertex coordinates and element connectivity to storage locations input by the application.  Assembling these data is a common task for writing mesh, and can be non-trivial when exporting only subsets of a mesh.  The writer interface declares the following functions:
 
-- get_node_arrays: Given already-allocated memory and the number of vertices and dimensions, and a range of vertices, this function writes vertex coordinates to that memory.  If a tag is input, that tag is also written with integer vertex ids, starting with 1, corresponding to the order the vertices appear in that sequence (these ids are used to write the connectivity array in the form of vertex indices).
-- get_element_array: Given a range of elements and the tag holding vertex ids, and a pointer to memory, the connectivity of the specified elements are written to that memory, in terms of the indices referenced by the specified tag.  Again, the number of vertices per element is input, to allow the direct output of higher-order vertices.
+- get_node_coords: Given already-allocated memory and the number of vertices and dimensions, and a range of vertices, this function writes vertex coordinates to that memory.  If a tag is input, that tag is also written with integer vertex ids, starting with 1, corresponding to the order the vertices appear in that sequence (these ids are used to write the connectivity array in the form of vertex indices).
+- get_element_connect: Given a range of elements and the tag holding vertex ids, and a pointer to memory, the connectivity of the specified elements are written to that memory, in terms of the indices referenced by the specified tag.  Again, the number of vertices per element is input, to allow the direct output of higher-order vertices.
 - gather_nodes_from_elements: Given a range of elements, this function returns the range of vertices used by those elements.  If a bit-type tag is input, vertices returned are also marked with 0x1 using that tag.  If no tag is input, the implementation of this function uses its own bit tag for marking, to avoid using an n2 algorithm for gathering vertices.
 - reorder: Given a permutation vector, this function reorders the connectivity for entities with specified type and number of vertices per entity to match that permutation.  This function is needed for writing connectivity into numbering systems other than that used internally in MOAB.
 .
@@ -557,11 +557,11 @@ iface->assign_ids(verts, 0, 1);
 // allocate space for coordinates & write them
 std::vector<double*> arrays(3);
 for (int i = 0; i < 3; i++) arrays[i] = new double[verts.size()];
-iface->get_node_arrays(3, verts.size(), verts, 0, 1, arrays);
+iface->get_node_coords(3, verts.size(), verts, 0, 1, arrays);
 
 // put connect’y in array, in the form of indices into vertex array
 std::vector<int> conn(8*hexes.size());
-iface->get_element_array(hexes.size(), 8, 0, hexes, 0, 1, &conn[0]);
+iface->get_element_connect(hexes.size(), 8, 0, hexes, 0, 1, &conn[0]);
 \endcode
 
  \ref 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 b9f7e0c..07f707f 100644
--- a/doc/user.dox.in
+++ b/doc/user.dox.in
@@ -30,7 +30,7 @@ PROJECT_NUMBER         =
 # If a relative path is entered, it will be relative to the location 
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = user
+OUTPUT_DIRECTORY       = 
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all 
 # documentation generated by doxygen is written. Doxygen will use this 
@@ -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/GetEntities.cpp b/examples/GetEntities.cpp
new file mode 100644
index 0000000..6c6a956
--- /dev/null
+++ b/examples/GetEntities.cpp
@@ -0,0 +1,60 @@
+/** @example GetEntities.cpp
+ * Description: Get entities and report non-vertex entity connectivity and vertex adjacencies.\n
+ * This example shows how to get connectivity and adjacencies.\n
+ *
+ * To run: ./GetEntities [meshfile]\n
+ * (default values can run if users don't specify a mesh file)
+ */
+
+#include "moab/Core.hpp"
+#include "moab/Range.hpp"
+#include "moab/CN.hpp"
+#include <iostream>
+
+using namespace moab;
+using namespace std;
+
+#ifndef MESH_DIR
+#define MESH_DIR "."
+#endif
+
+string test_file_name = string(MESH_DIR) + string("/1hex.g");
+
+int main(int argc, char **argv) {
+
+  if (argc > 1){
+    //user has input a mesh file
+    test_file_name = argv[1];
+  }  
+    // instantiate & load a mesh from a file
+  Core *mb = new Core();
+  ErrorCode rval = mb->load_mesh(test_file_name.c_str());
+  if (MB_SUCCESS != rval) return 1;
+
+  Range ents;
+
+    // get all entities in the database
+  rval = mb->get_entities_by_handle(0, ents);
+  if (MB_SUCCESS != rval) return 1;
+
+  for (Range::iterator it = ents.begin(); it != ents.end(); it++) {
+    if (MBVERTEX == mb->type_from_handle(*it)) {
+      Range adjs;
+      rval = mb->get_adjacencies(&(*it), 1, 3, false, adjs);
+      if (MB_SUCCESS != rval) return 1;
+      cout << "Vertex " << mb->id_from_handle(*it) << " adjacencies:" << endl;
+      adjs.print();
+    }
+    else if (mb->type_from_handle(*it) < MBENTITYSET) {
+      const EntityHandle *connect;
+      int num_connect;
+      rval = mb->get_connectivity(*it, connect, num_connect);
+      if (MB_SUCCESS != rval) return 1;
+      cout << CN::EntityTypeName(mb->type_from_handle(*it)) << " " << mb->id_from_handle(*it) << " vertex connectivity is: ";
+      for (int i = 0; i < num_connect; i++) cout << mb->id_from_handle(connect[i]) << " ";
+      cout << endl;
+    }
+  }
+  
+  return 0;
+}

diff --git a/examples/HelloMOAB.cpp b/examples/HelloMOAB.cpp
index ebab971..6129233 100644
--- a/examples/HelloMOAB.cpp
+++ b/examples/HelloMOAB.cpp
@@ -2,7 +2,7 @@
  * Description: read a mesh, get the entities.\n
  * HelloMOAB is a simple test file which is used to read meshes from VTK file and test how many entities there are.\n
  *
- * To run: ./HelloMOAB <meshfile>\n
+ * To run: ./HelloMOAB [meshfile]\n
  * (default values can run if users don't specify a mesh file)
  */
 
@@ -14,6 +14,10 @@
 using namespace moab;
 using namespace std;
 
+#ifndef MESH_DIR
+#define MESH_DIR "."
+#endif
+
 string test_file_name = string(MESH_DIR) + string("/3k-tri-sphere.vtk");
 
 int main( int argc, char** argv )
@@ -27,38 +31,32 @@ int main( int argc, char** argv )
   }  
     //load the mesh from vtk file
   ErrorCode rval = iface->load_mesh( test_file_name.c_str() );
-  assert( rval == MB_SUCCESS);
+  assert(rval == MB_SUCCESS);
 
-    //get verts entities
+    // get verts entities, by type
   Range verts;
   rval = iface->get_entities_by_type(0, MBVERTEX, verts);
-  assert( rval == MB_SUCCESS);
-    //get edge entities
+  assert(rval == MB_SUCCESS);
+    //get edge entities, by type
   Range edges;
   rval = iface->get_entities_by_type(0, MBEDGE, edges);
   assert(rval == MB_SUCCESS);
 
-    //get triangular entities
-  Range tri;
-  rval = iface->get_entities_by_type(0, MBTRI, tri);
-  assert( rval == MB_SUCCESS);
-
-    //get quad entities
-  Range quads;
-  rval = iface->get_entities_by_type(0, MBQUAD, quads);
+    // get faces, by dimension, so we stay generic to entity type
+  Range faces;
+  rval = iface->get_entities_by_dimension(0, 2, faces);
   assert(rval == MB_SUCCESS);
 
-    //get hex entities
-  Range hex;
-  rval = iface->get_entities_by_type(0, MBHEX, hex);
+    //get regions, by dimension, so we stay generic to entity type
+  Range elems;
+  rval = iface->get_entities_by_dimension(0, 3, elems);
   assert(rval == MB_SUCCESS);
 
    //output the number of entities
   cout << "Number of vertices is " << verts.size() <<  endl;
   cout << "Number of edges is " << edges.size() <<  endl;
-  cout << "Number of triangular faces is " << tri.size() <<  endl;
-  cout << "Number of quad faces is " << quads.size() <<  endl;
-  cout << "Number of hex is " << hex.size() <<  endl;
+  cout << "Number of faces is " << faces.size() <<  endl;
+  cout << "Number of elements is " << elems.size() <<  endl;
   
   return 0;
 }

diff --git a/examples/HelloMoabPar.cpp b/examples/HelloMoabPar.cpp
deleted file mode 100644
index a5a71aa..0000000
--- a/examples/HelloMoabPar.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/** @example HelloMoabPar.cpp \n
- * \brief Read mesh into MOAB in parallel \n
- * This example shows the simplest way of telling MOAB to read in parallel.
- *
- *    -#  Initialize MPI and get the rank and number of processors \n
- *    -#  Process arguments (file name and options for parallel read) \n
- *    -#  Initialize MOAB \n
- *    -#  Load a partitioned file in parallel; \n
- *    -#  retrieve shared entities on each processor \n
- *    -#  Filter owned entities among shared ones on each processor \n
- *    -#  Exchange ghost layers, and repeat the reports \n
- *
- * <b>To compile</b>: \n
- *    make HelloMoabPar MOAB_DIR=<installdir>  \n
- * <b>To run</b>: mpiexec -np 4 HelloMoabPar \n
- *  (depending on your configuration, LD_LIBRARY_PATH may need to contain <hdf5>/lib folder)
- *
- */
-
-#include "moab/ParallelComm.hpp"
-#include "MBParallelConventions.h"
-#include "moab/Core.hpp"
-#include <iostream>
-
-using namespace moab;
-
-int main(int argc, char **argv)
-{
-  MPI_Init(&argc, &argv);
-
-  int nprocs, rank;
-  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
-  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-
-  std::string filename;
-  std::string options;
-  if (3 != argc)
-  {
-    if (rank == 0)
-    {
-      std::cout << "Usage: " << argv[0] << " <filename><options (separated by;)>\n ";
-    }
-    /* this file has a partition with 4 parts */
-    filename = "../MeshFiles/unittest/disk.h5m";
-    /*  Options for reading
-     *  - read in parallel
-     *  - use PARALLEL_PARTITION tag
-     *  - resolve shared entities after reading
-    */
-    options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
-  }
-  else
-  {
-    filename = argv[1];
-    options = argv[2];
-  }
-  if (rank == 0)
-    std::cout << "reading file " << filename << "\n  with options:" << options <<
-      "\n  on " << nprocs << " processors\n";
-
-  // get MOAB instance and read the file with the specified options
-  Interface *mbImpl = new Core;
-  if (NULL == mbImpl) return 1;
-  ErrorCode rval = mbImpl->load_file(filename.c_str(), 0, options.c_str());
-  if (rval != MB_SUCCESS) return 1;
-
-  // get the ParallelComm instance
-  ParallelComm* pcomm = ParallelComm::get_pcomm(mbImpl, 0);
-  MPI_Comm comm = pcomm->comm();
-  if (0 == pcomm) return 1;
-
-  // get all shared entities with other processors
-  Range shared_ents;
-  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
-      shared_ents);
-  if (rval != MB_SUCCESS) return 1;
-  /* Among shared entities, get those owned by the current processor
-   * For this, use a filter operation;
-   * Each shared entity is owned by exactly one processor;
-   * An entity could be simply-shared (with exactly one other processor) or
-   *  multi-shared.
-   */
-  Range owned_entities;
-  rval = pcomm->filter_pstatus(shared_ents, // pass entities that we want to filter
-      PSTATUS_NOT_OWNED, // status we are looking for
-      PSTATUS_NOT, // operation applied ; so it will return owned entities (!not_owned = owned)
-      -1, // this means all processors
-      &owned_entities);
-  if (rval != MB_SUCCESS) return 1;
-  unsigned int nums[4]={0}; // to store the owned entities per dimension
-  for (int i=0; i<3; i++)
-  {
-    nums[i]=(int)owned_entities.num_of_dimension(i);
-  }
-  int * rbuf;
-  if (rank==0)
-    rbuf = (int *)malloc(nprocs*4*sizeof(int));
-  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
-  // print the stats gathered:
-  if (rank == 0)
-  {
-    for (int i=0; i<nprocs; i++)
-    {
-      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
-    }
-
-  }
-
-  /*
-   * Now exchange 1 layer of ghost elements, using vertices as bridge
-   *   we could have done this as part of reading process, by passing an extra read option
-   *    ";PARALLEL_GHOSTS=2.0.1.0"
-   */
-  rval = pcomm->exchange_ghost_cells(2, // int ghost_dim,
-                                     0, // int bridge_dim,
-                                     1, //int num_layers,
-                                     0, //int addl_ents,
-                                     true); // bool store_remote_handles);
-  if (rval != MB_SUCCESS) return 1;
-
-  // repeat the reports, after ghost exchange
-  shared_ents.clear();
-  owned_entities.clear();
-  rval = pcomm->get_shared_entities(-1, // -1 means all other processors                                    Range &shared_ents,
-        shared_ents);
-  if (rval != MB_SUCCESS) return 1;
-  rval = pcomm->filter_pstatus(shared_ents,
-        PSTATUS_NOT_OWNED,
-        PSTATUS_NOT,
-        -1,
-        &owned_entities);
-  if (rval != MB_SUCCESS)  return 1;
-
-  // find out how many shared entities of each dimension are owned on this processor
-  for (int i=0; i<3; i++)
-    nums[i]=(int)owned_entities.num_of_dimension(i);
-
-  // gather the statistics on processor 0
-  MPI_Gather( nums, 4, MPI_INT, rbuf, 4, MPI_INT, 0, comm);
-  if (rank == 0)
-  {
-    std::cout << " \n\n After exchanging one ghost layer: \n";
-    for (int i=0; i<nprocs; i++)
-    {
-      std::cout << " shared, owned entities on proc " << i << " :" << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces\n";
-    }
-    free(rbuf);
-  }
-  MPI_Finalize();
-
-  return 0;
-}

diff --git a/examples/HelloParMOAB.cpp b/examples/HelloParMOAB.cpp
new file mode 100644
index 0000000..75daeda
--- /dev/null
+++ b/examples/HelloParMOAB.cpp
@@ -0,0 +1,103 @@
+/** @example HelloParMOAB.cpp \n
+ * \brief Read mesh into MOAB and resolve/exchange/report shared and ghosted entities \n
+ * <b>To run</b>: mpiexec -np 4 HelloMoabPar [filename]\n
+ *
+ */
+
+#include "moab/ParallelComm.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Core.hpp"
+#include <iostream>
+
+using namespace moab;
+using namespace std;
+
+string test_file_name = string(MESH_DIR) + string("/64bricks_512hex_256part.h5m");
+
+int main(int argc, char **argv)
+{
+  MPI_Init(&argc, &argv);
+
+  string options;
+
+    // need option handling here for input filename
+  if (argc > 1){
+    //user has input a mesh file
+    test_file_name = argv[1];
+  }  
+
+  options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
+
+  // get MOAB instance and read the file with the specified options
+  Interface *mb = new Core;
+  if (NULL == mb) return 1;
+  // get the ParallelComm instance
+  ParallelComm* pcomm = new ParallelComm(mb, MPI_COMM_WORLD);
+  int nprocs = pcomm->proc_config().proc_size(), rank = pcomm->proc_config().proc_rank();
+  MPI_Comm comm = pcomm->proc_config().proc_comm();
+
+  if (rank == 0)
+    cout << "Reading file " << test_file_name << "\n  with options: " << options << endl
+         << " on " << nprocs << " processors\n";
+
+  ErrorCode rval = mb->load_file(test_file_name.c_str(), 0, options.c_str());
+  if (rval != MB_SUCCESS) return 1;
+
+  Range shared_ents;
+    // get entities shared with all other processors
+  rval = pcomm->get_shared_entities(-1, shared_ents);
+  if (rval != MB_SUCCESS) return 1;
+
+    // filter shared entities with not not_owned, which means owned
+  Range owned_entities;
+  rval = pcomm->filter_pstatus(shared_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_entities);
+  if (rval != MB_SUCCESS) return 1;
+
+  unsigned int nums[4]={0}; // to store the owned entities per dimension
+  for (int i=0; i<4; i++) nums[i]=(int)owned_entities.num_of_dimension(i);
+  vector<int> rbuf(nprocs*4, 0);
+  MPI_Gather( nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, MPI_COMM_WORLD);
+  // print the stats gathered:
+  if (rank == 0) {
+    for (int i=0; i<nprocs; i++)
+      cout << " Shared, owned entities on proc " << i << ": " << rbuf[4*i] << " verts, " <<
+          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces, " << rbuf[4*i+3] << " elements" << endl;
+  }
+
+    // Now exchange 1 layer of ghost elements, using vertices as bridge
+    // (we could have done this as part of reading process, using the PARALLEL_GHOSTS read option)
+  rval = pcomm->exchange_ghost_cells(3, // int ghost_dim,
+                                     0, // int bridge_dim,
+                                     1, //int num_layers,
+                                     0, //int addl_ents,
+                                     true); // bool store_remote_handles);
+  if (rval != MB_SUCCESS) return 1;
+
+  // repeat the reports, after ghost exchange
+  shared_ents.clear();
+  owned_entities.clear();
+  rval = pcomm->get_shared_entities(-1, shared_ents);
+  if (rval != MB_SUCCESS) return 1;
+  rval = pcomm->filter_pstatus(shared_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_entities);
+  if (rval != MB_SUCCESS)  return 1;
+
+  // find out how many shared entities of each dimension are owned on this processor
+  for (int i=0; i<4; i++)
+    nums[i]=(int)owned_entities.num_of_dimension(i);
+
+  // gather the statistics on processor 0
+  MPI_Gather( nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, comm);
+  if (rank == 0)
+  {
+    cout << " \n\n After exchanging one ghost layer: \n";
+    for (int i=0; i<nprocs; i++)
+    {
+      cout << " Shared, owned entities on proc " << i << ": " << rbuf[4*i] << " verts, " <<
+          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces, " << rbuf[4*i+3] << " elements" << endl;
+    }
+  }
+
+  MPI_Finalize();
+
+  return 0;
+}

diff --git a/examples/LloydRelaxation.cpp b/examples/LloydRelaxation.cpp
new file mode 100644
index 0000000..0cf9d1e
--- /dev/null
+++ b/examples/LloydRelaxation.cpp
@@ -0,0 +1,219 @@
+/** @example LloydRelaxation.cpp \n
+ * \brief Perform Lloyd relaxation on a mesh and its dual \n
+ * <b>To run</b>: mpiexec -np <np> LloydRelaxation [filename]\n
+ *
+ * Briefly, Lloyd relaxation is a technique to smooth out a mesh.  The centroid of each cell is computed from its
+ * vertex positions, then vertices are placed at the average of their connected cells' centroids.
+ *
+ * In the parallel algorithm, an extra ghost layer of cells is exchanged.  This allows us to compute the centroids
+ * for boundary cells on each processor where they appear; this eliminates the need for one round of data exchange
+ * (for those centroids) between processors.  New vertex positions must be sent from owning processors to processors
+ * sharing those vertices.  Convergence is measured as the maximum distance moved by any vertex.  
+ * 
+ * In this implementation, a fixed number of iterations is performed.  The final mesh is output to 'lloydfinal.h5m'
+ * in the current directory (H5M format must be used since the file is written in parallel).
+ */
+
+#include "moab/ParallelComm.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Core.hpp"
+#include "moab/Skinner.hpp"
+#include "moab/CN.hpp"
+#include "moab/CartVect.hpp"
+#include <iostream>
+#include <sstream>
+
+using namespace moab;
+using namespace std;
+
+string test_file_name = string(MESH_DIR) + string("/surfrandomtris-4part.h5m");
+
+#define RC if (MB_SUCCESS != rval) return rval
+
+ErrorCode perform_lloyd_relaxation(ParallelComm *pc, Range &verts, Range &cells, Tag fixed, 
+                                   int num_its, int report_its);
+
+int main(int argc, char **argv)
+{
+  int num_its = 10;
+  int report_its = 1;
+
+  MPI_Init(&argc, &argv);
+
+    // need option handling here for input filename
+  if (argc > 1){
+    //user has input a mesh file
+    test_file_name = argv[1];
+  }  
+
+  // get MOAB and ParallelComm instances
+  Interface *mb = new Core;
+  if (NULL == mb) return 1;
+  // get the ParallelComm instance
+  ParallelComm* pcomm = new ParallelComm(mb, MPI_COMM_WORLD);
+  int nprocs = pcomm->size();
+
+  string options;
+  if (nprocs > 1) // if reading in parallel, need to tell it how
+    options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARALLEL_GHOSTS=2.0.1;DEBUG_IO=0;DEBUG_PIO=0";
+
+    // read the file
+  ErrorCode rval = mb->load_file(test_file_name.c_str(), 0, options.c_str()); RC;
+
+    // make tag to specify fixed vertices, since it's input to the algorithm; use a default value of non-fixed
+    // so we only need to set the fixed tag for skin vertices
+  Tag fixed;
+  int def_val = 0;
+  rval = mb->tag_get_handle("fixed", 1, MB_TYPE_INTEGER, fixed, MB_TAG_CREAT | MB_TAG_DENSE, &def_val); RC;
+
+    // get all vertices and faces
+  Range verts, faces, skin_verts;
+  rval = mb->get_entities_by_type(0, MBVERTEX, verts); RC;
+  rval = mb->get_entities_by_dimension(0, 2, faces); RC;
+  
+    // get the skin vertices of those faces and mark them as fixed; we don't want to fix the vertices on a
+    // part boundary, but since we exchanged a layer of ghost faces, those vertices aren't on the skin locally
+    // ok to mark non-owned skin vertices too, I won't move those anyway
+    // use MOAB's skinner class to find the skin
+  Skinner skinner(mb);
+  rval = skinner.find_skin(faces, true, skin_verts); RC; // 'true' param indicates we want vertices back, not faces
+
+  std::vector<int> fix_tag(skin_verts.size(), 1); // initialized to 1 to indicate fixed
+  rval = mb->tag_set_data(fixed, skin_verts, &fix_tag[0]); RC;
+
+    // now perform the Lloyd relaxation
+  rval = perform_lloyd_relaxation(pcomm, verts, faces, fixed, num_its, report_its); RC;
+
+    // delete fixed tag, since we created it here
+  rval = mb->tag_delete(fixed); RC;
+  
+    // output file, using parallel write
+  rval = mb->write_file("lloydfinal.h5m", NULL, "PARALLEL=WRITE_PART"); RC;
+
+    // delete MOAB instance
+  delete mb;
+  
+  MPI_Finalize();
+
+  return 0;
+}
+
+ErrorCode perform_lloyd_relaxation(ParallelComm *pcomm, Range &verts, Range &faces, Tag fixed, 
+                                   int num_its, int report_its) 
+{
+  ErrorCode rval;
+  Interface *mb = pcomm->get_moab();
+  int nprocs = pcomm->size();
+  
+    // perform Lloyd relaxation:
+    // 1. setup: set vertex centroids from vertex coords; filter to owned verts; get fixed tags
+
+    // get all verts coords into tag; don't need to worry about filtering out fixed verts, 
+    // we'll just be setting to their fixed coords
+  std::vector<double> vcentroids(3*verts.size());
+  rval = mb->get_coords(verts, &vcentroids[0]); RC;
+
+  Tag centroid;
+  rval = mb->tag_get_handle("centroid", 3, MB_TYPE_DOUBLE, centroid, MB_TAG_CREAT | MB_TAG_DENSE); RC;
+  rval = mb->tag_set_data(centroid, verts, &vcentroids[0]); RC;
+
+    // filter verts down to owned ones and get fixed tag for them
+  Range owned_verts, shared_owned_verts;
+  if (nprocs > 1) {
+    rval = pcomm->filter_pstatus(verts, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_verts);
+    if (rval != MB_SUCCESS) return rval;
+  }
+  else
+    owned_verts = verts;
+  std::vector<int> fix_tag(owned_verts.size());
+  rval = mb->tag_get_data(fixed, owned_verts, &fix_tag[0]); RC;
+
+    // now fill vcentroids array with positions of just owned vertices, since those are the ones
+    // we're actually computing
+  vcentroids.resize(3*owned_verts.size());
+  rval = mb->tag_get_data(centroid, owned_verts, &vcentroids[0]); RC;
+
+    // get shared owned verts, for exchanging tags
+  rval = pcomm->get_shared_entities(-1, shared_owned_verts, 0, false, true); RC;
+    // workaround: if no shared owned verts, put a non-shared one in the list, to prevent exchanging tags
+    // for all shared entities
+  if (shared_owned_verts.empty()) shared_owned_verts.insert(*verts.begin());
+  
+    // some declarations for later iterations
+  std::vector<double> fcentroids(3*faces.size()); // fcentroids for face centroids
+  std::vector<double> ctag(3*CN::MAX_NODES_PER_ELEMENT);  // temporary coordinate storage for verts bounding a face
+  const EntityHandle *conn;  // const ptr & size to face connectivity
+  int nconn;
+  Range::iterator fit, vit;  // for iterating over faces, verts
+  int f, v;  // for indexing into centroid vectors
+  std::vector<EntityHandle> adj_faces;  // used in vertex iteration
+  
+    // 2. for num_its iterations:
+  for (int nit = 0; nit < num_its; nit++) {
+    
+    double mxdelta = 0.0;
+
+    // 2a. foreach face: centroid = sum(vertex centroids)/num_verts_in_cell
+    for (fit = faces.begin(), f = 0; fit != faces.end(); fit++, f++) {
+        // get verts for this face
+      rval = mb->get_connectivity(*fit, conn, nconn); RC;
+        // get centroid tags for those verts
+      rval = mb->tag_get_data(centroid, conn, nconn, &ctag[0]); RC;
+      fcentroids[3*f+0] = fcentroids[3*f+1] = fcentroids[3*f+2] = 0.0;
+      for (v = 0; v < nconn; v++) {
+        fcentroids[3*f+0] += ctag[3*v+0];
+        fcentroids[3*f+1] += ctag[3*v+1];
+        fcentroids[3*f+2] += ctag[3*v+2];
+      }
+      for (v = 0; v < 3; v++) fcentroids[3*f+v] /= nconn;
+    }
+    rval = mb->tag_set_data(centroid, faces, &fcentroids[0]); RC;
+
+      // 2b. foreach owned vertex: 
+    for (vit = owned_verts.begin(), v = 0; vit != owned_verts.end(); vit++, v++) {
+        // if !fixed
+      if (fix_tag[v]) continue;
+        // vertex centroid = sum(cell centroids)/ncells
+      adj_faces.clear();
+      rval = mb->get_adjacencies(&(*vit), 1, 2, false, adj_faces); RC;
+      rval = mb->tag_get_data(centroid, &adj_faces[0], adj_faces.size(), &fcentroids[0]); RC;
+      double vnew[] = {0.0, 0.0, 0.0};
+      for (f = 0; f < (int)adj_faces.size(); f++) {
+        vnew[0] += fcentroids[3*f+0];
+        vnew[1] += fcentroids[3*f+1];
+        vnew[2] += fcentroids[3*f+2];
+      }
+      for (f = 0; f < 3; f++) vnew[f] /= adj_faces.size();
+      double delta = (CartVect(vnew)-CartVect(&vcentroids[3*v])).length();
+      mxdelta = std::max(delta, mxdelta);
+      for (f = 0; f < 3; f++) vcentroids[3*v+f] = vnew[f];
+    }
+
+      // set the centroid tag; having them only in vcentroids array isn't enough, as vertex centroids are
+      // accessed randomly in loop over faces
+    rval = mb->tag_set_data(centroid, owned_verts, &vcentroids[0]); RC;
+
+    // 2c. exchange tags on owned verts
+    if (nprocs > 1) {
+      rval = pcomm->exchange_tags(centroid, shared_owned_verts); RC;
+    }
+
+
+    if (!(nit%report_its)) {
+        // global reduce for maximum delta, then report it
+      double global_max = mxdelta;
+      if (nprocs > 1)
+        MPI_Reduce(&mxdelta, &global_max, 1, MPI_DOUBLE, MPI_MAX, 0, pcomm->comm());
+      if (1 == nprocs || !pcomm->rank()) 
+        cout << "Max delta = " << global_max << endl;
+    }
+  }
+  
+    // write the tag back onto vertex coordinates
+  rval = mb->set_coords(owned_verts, &vcentroids[0]); RC;
+
+    // delete the centroid tag, since we don't need it anymore
+  rval = mb->tag_delete(centroid); RC;
+  
+  return MB_SUCCESS;
+}

diff --git a/examples/SetsNTags.cpp b/examples/SetsNTags.cpp
new file mode 100644
index 0000000..e2071c1
--- /dev/null
+++ b/examples/SetsNTags.cpp
@@ -0,0 +1,77 @@
+/** @example SetsNTags.cpp
+ * Description: Get the sets representing materials and Dirichlet/Neumann boundary conditions and list their contents.\n
+ * This example shows how to get entity sets, and tags on those sets.
+ *
+ * To run: ./SetsNTags [meshfile]\n
+ * (default values can run if users don't specify a mesh file)
+ */
+
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "moab/Range.hpp"
+#include "MBTagConventions.hpp"
+
+#include <iostream>
+
+using namespace moab;
+using namespace std;
+
+#ifndef MESH_DIR
+#define MESH_DIR "."
+#endif
+
+string test_file_name = string(MESH_DIR) + string("/1hex.g");
+
+// tag names for these conventional tags come from MBTagConventions.hpp
+const char *tag_nms[] = {MATERIAL_SET_TAG_NAME, DIRICHLET_SET_TAG_NAME, NEUMANN_SET_TAG_NAME};
+
+int main(int argc, char **argv) {
+    // get the material set tag handle
+  Tag mtag;
+  ErrorCode rval;
+  Range sets, set_ents;
+
+    // instantiate & load a file
+  Interface *mb = new Core();
+
+    // need option handling here for input filename
+  if (argc > 1){
+    //user has input a mesh file
+    test_file_name = argv[1];
+  }  
+
+  rval = mb->load_file(test_file_name.c_str());
+  if (MB_SUCCESS != rval) return 1;
+
+    // loop over set types
+  for (int i = 0; i < 3; i++) {
+      // get the tag handle for this tag name; tag should already exist (it was created during file read)
+    rval = mb->tag_get_handle(tag_nms[i], 1, MB_TYPE_INTEGER, mtag);
+    if (MB_SUCCESS != rval) return 1;
+
+      // get all the sets having that tag (with any value for that tag)
+    sets.clear();
+    rval = mb->get_entities_by_type_and_tag(0, MBENTITYSET, &mtag, NULL, 1, sets);
+    if (MB_SUCCESS != rval) return 1;
+
+      // iterate over each set, getting the entities and printing them
+    Range::iterator set_it;
+    for (set_it = sets.begin(); set_it != sets.end(); set_it++)  {
+        // get the id for this set
+      int set_id;
+      rval = mb->tag_get_data(mtag, &(*set_it), 1, &set_id);
+      if (MB_SUCCESS != rval) return 1;
+
+        // get the entities in the set, recursively
+      rval = mb->get_entities_by_handle(*set_it, set_ents, true);
+      if (MB_SUCCESS != rval) return 1;
+
+      cout << tag_nms[i] << " " << set_id << " has " 
+                << set_ents.size() << " entities:" << endl;
+      set_ents.print("   ");
+      set_ents.clear();
+    }
+  }
+
+  delete mb;
+}

diff --git a/examples/makefile b/examples/makefile
index 3402f96..3b848d2 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -7,21 +7,28 @@ include ${MOAB_DIR}/lib/iMesh-Defs.inc
 # MESH_DIR is the top-level MOAB source directory, used to locate mesh files that come with MOAB source
 MESH_DIR="../MeshFiles/unittest"
 
-StructuredMeshSimple : StructuredMeshSimple.o
-	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
+EXAMPLES = HelloMOAB GetEntities SetsNTags StructuredMeshSimple DirectAccessWithHoles DirectAccessNoHoles 
+PAREXAMPLES = HelloParMOAB ReduceExchangeTags LloydRelaxation
+F90EXAMPLES = DirectAccessNoHolesF90
+EXOIIEXAMPLES = TestExodusII
+
+default: ${EXAMPLES}
 
 HelloMOAB : HelloMOAB.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-ReduceExchangeTags : ReduceExchangeTags.o
+GetEntities: GetEntities.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-HelloMoabPar: HelloMoabPar.o
-	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
+SetsNTags: SetsNTags.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-TestExodusII: TestExodusII.o
+LloydRelaxation: LloydRelaxation.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+StructuredMeshSimple : StructuredMeshSimple.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
+
 DirectAccessWithHoles: DirectAccessWithHoles.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
@@ -31,6 +38,18 @@ DirectAccessNoHoles: DirectAccessNoHoles.o
 DirectAccessNoHolesF90: DirectAccessNoHolesF90.o
 	${MOAB_CXX} -o $@ $< ${IMESH_LIBS}
 
+ReduceExchangeTags : ReduceExchangeTags.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
+
+HelloParMOAB: HelloParMOAB.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
+
+TestExodusII: TestExodusII.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
+
+clean:
+	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
+
 .cpp.o :
 	${MOAB_CXX} ${MOAB_CXXFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 

diff --git a/examples/old/SetsNTags.cpp b/examples/old/SetsNTags.cpp
deleted file mode 100644
index 9930891..0000000
--- a/examples/old/SetsNTags.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "moab/Core.hpp"
-#include "moab/Interface.hpp"
-#include "moab/Range.hpp"
-
-#ifdef USE_MPI
-#include "moab_mpi.h"
-#endif
-
-#include <iostream>
-
-int main(int argc, char **argv) {
-    // get the material set tag handle
-  moab::Tag mtag;
-  moab::ErrorCode rval;
-  const char *tag_nms[] = {"MATERIAL_SET", "DIRICHLET_SET", "NEUMANN_SET"};
-  moab::Range sets, set_ents;
-
-    // instantiate & load a file
-  moab::Interface *mb = new moab::Core();
-  const char *par_opt = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS;SETS=SETS";
-
-  bool parallel = false;
-  if (argc > 2 && !strcmp(argv[1], "-p")) parallel = true;
-  else if (argc == 1) {
-    std::cout << "Usage: " << argv[0] << "[-p] <filename>" << std::endl;
-    return 0;
-  }
-
-  if (parallel) 
-    rval = mb->load_file(argv[argc-1], 0, par_opt);
-  else
-    rval = mb->load_file(argv[argc-1]);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // loop over set types
-  for (int i = 0; i < 3; i++) {
-    rval = mb->tag_get_handle(tag_nms[i], 1, moab::MB_TYPE_INTEGER, mtag);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // get all the sets of that type in the mesh
-    sets.clear();
-    rval = mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &mtag,
-                                            NULL, 1, sets);
-    if (moab::MB_SUCCESS != rval) return 1;
-
-      // iterate over each set, getting entities
-    moab::Range::iterator set_it;
-    for (set_it = sets.begin(); set_it != sets.end(); set_it++)  {
-      moab::EntityHandle this_set = *set_it;
-
-        // get the id for this set
-      int set_id;
-      rval = mb->tag_get_data(mtag, &this_set, 1, &set_id);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-        // get the entities in the set, recursively
-      rval = mb->get_entities_by_handle(this_set, set_ents, true);
-      if (moab::MB_SUCCESS != rval) return 1;
-
-      std::cout << tag_nms[i] << " " << set_id << " has " 
-                << set_ents.size() << " entities:" << std::endl;
-      set_ents.print("   ");
-      set_ents.clear();
-    }
-  }
-
-    // do the same for all sets
-  sets.clear();
-  rval = mb->get_entities_by_type(0, moab::MBENTITYSET, sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-    // print the sets
-  rval = mb->list_entities(sets);
-  if (moab::MB_SUCCESS != rval) return 1;
-
-  rval = mb->list_entities(NULL, 1);
-  
-#ifdef USE_MPI
-  if (parallel) {
-    MPI_Barrier(MPI_COMM_WORLD);
-    std::cout << std::flush;
-    std::cerr << std::flush;
-  }
-#endif
-
-  delete mb;
-}

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 7d1a6c3..d28c824 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -83,12 +83,12 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
       {
         if (vdatas[i].varDims.size() != 1)
         {
-          vdatas[i].readDims[t].push_back(tstep_nums[t]);
+          vdatas[i].readStarts[t].push_back(tstep_nums[t]);
           vdatas[i].readCounts[t].push_back(1);
         }
         else
         {
-          vdatas[i].readDims[t].push_back(0);
+          vdatas[i].readStarts[t].push_back(0);
           vdatas[i].readCounts[t].push_back(tstep_nums.size());
         }
       }
@@ -96,14 +96,14 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
       // Set up other dimensions and counts
       if (vdatas[i].varDims.empty()) {
         // Scalar variable
-        vdatas[i].readDims[t].push_back(0);
+        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].readDims[t].push_back(0);
+            vdatas[i].readStarts[t].push_back(0);
             vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[idx]]);
           }
         }
@@ -158,28 +158,28 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         case NC_CHAR:
-          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               (char*) data NCREQ);
           ERRORS(success, "Failed to read char data.");
           break;
         case NC_DOUBLE:
-          success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               (double*) data NCREQ);
           ERRORS(success, "Failed to read double data.");
           break;
         case NC_FLOAT: {
-          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               (float*) data NCREQ);
           ERRORS(success, "Failed to read float data.");
           break;
         }
         case NC_INT:
-          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               (int*) data NCREQ);
           ERRORS(success, "Failed to read int data.");
           break;
         case NC_SHORT:
-          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               (short*) data NCREQ);
           ERRORS(success, "Failed to read short data.");
           break;
@@ -545,7 +545,7 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
     for (unsigned int i = 0; i < vdatas.size(); i++) {
       vdatas[i].varTags.resize(tstep_nums.size(), 0);
       vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readDims.resize(tstep_nums.size());
+      vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
@@ -553,13 +553,13 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
           && (vsetdatas[i].varDims.size() != 1)) {
         vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
         vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readDims.resize(tstep_nums.size());
+        vsetdatas[i].readStarts.resize(tstep_nums.size());
         vsetdatas[i].readCounts.resize(tstep_nums.size());
       }
       else {
         vsetdatas[i].varTags.resize(1, 0);
         vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readDims.resize(1);
+        vsetdatas[i].readStarts.resize(1);
         vsetdatas[i].readCounts.resize(1);
       }
     }
@@ -647,12 +647,12 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
 
       // Set up the dimensions and counts
       // First time
-      vdatas[i].readDims[t].push_back(tstep_nums[t]);
+      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
       vdatas[i].readCounts[t].push_back(1);
 
       // then z/y/x
       if (vdatas[i].numLev != 1) {
-        vdatas[i].readDims[t].push_back(0);
+        vdatas[i].readStarts[t].push_back(0);
         vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
       }
 
@@ -660,11 +660,11 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
         case ReadNC::ENTLOCVERT:
           // vertices
           // only structured mesh has j parameter that multiplies i to get total # vertices
-          vdatas[i].readDims[t].push_back(lDims[1]);
+          vdatas[i].readStarts[t].push_back(lDims[1]);
           vdatas[i].readCounts[t].push_back(lDims[4] - lDims[1] + 1);
-          vdatas[i].readDims[t].push_back(lDims[0]);
+          vdatas[i].readStarts[t].push_back(lDims[0]);
           vdatas[i].readCounts[t].push_back(lDims[3] - lDims[0] + 1);
-          assert(vdatas[i].readDims[t].size() == vdatas[i].varDims.size());
+          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
           range = &verts;
           break;
         case ReadNC::ENTLOCNSEDGE:
@@ -675,11 +675,11 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle file_se
           break;
         case ReadNC::ENTLOCFACE:
           // faces
-          vdatas[i].readDims[t].push_back(lCDims[1]);
-          vdatas[i].readDims[t].push_back(lCDims[0]);
+          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);
           vdatas[i].readCounts[t].push_back(lCDims[3] - lCDims[0] + 1);
-          assert(vdatas[i].readDims[t].size() == vdatas[i].varDims.size());
+          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
 #ifdef USE_MPI
           range = &faces_owned;
 #else
@@ -737,7 +737,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         case NC_BYTE:
         case NC_CHAR: {
           std::vector<char> tmpchardata(sz);
-          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          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
@@ -751,7 +751,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         }
         case NC_DOUBLE: {
           std::vector<double> tmpdoubledata(sz);
-          success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          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
@@ -765,7 +765,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         }
         case NC_FLOAT: {
           std::vector<float> tmpfloatdata(sz);
-          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               &tmpfloatdata[0] NCREQ);
           if (vdatas[i].numLev != 1)
             // Switch from k varying slowest to k varying fastest
@@ -779,7 +779,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         }
         case NC_INT: {
           std::vector<int> tmpintdata(sz);
-          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               &tmpintdata[0] NCREQ);
           if (vdatas[i].numLev != 1)
             // Switch from k varying slowest to k varying fastest
@@ -793,7 +793,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         }
         case NC_SHORT: {
           std::vector<short> tmpshortdata(sz);
-          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[t][0], &vdatas[i].readCounts[t][0],
               &tmpshortdata[0] NCREQ);
           if (vdatas[i].numLev != 1)
             // Switch from k varying slowest to k varying fastest

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index d6659eb..0a7802f 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -247,9 +247,6 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions& opts
   DebugOutput& dbgOut = _readNC->dbgOut;
   bool& isParallel = _readNC->isParallel;
   Range& localGid = _readNC->localGid;
-#ifdef USE_MPI
-  ParallelComm*& myPcomm = _readNC->myPcomm;
-#endif
   bool& spectralMesh = _readNC->spectralMesh;
   int& gatherSetRank = _readNC->gatherSetRank;
 
@@ -270,22 +267,24 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions& opts
 
   int success;
 
-  int rank, procs;
-#ifdef PNETCDF_FILE
+  int rank = 0, procs = 1;
+#ifdef USE_MPI
   if (isParallel) {
-    success = NCFUNC(open)(myPcomm->proc_config().proc_comm(), conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
+    ParallelComm*& myPcomm = _readNC->myPcomm;
     rank = myPcomm->proc_config().proc_rank();
     procs = myPcomm->proc_config().proc_size();
   }
+#endif
+
+#ifdef PNETCDF_FILE
+  if (isParallel) {
+    success = NCFUNC(open)(myPcomm->proc_config().proc_comm(), conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
+  }
   else {
     success = NCFUNC(open)(MPI_COMM_SELF, conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
-    rank = 0;
-    procs = 1;
   }
 #else
   success = NCFUNC(open)(conn_fname.c_str(), 0, &connectId);
-  rank = 0;
-  procs = 1;
 #endif
   ERRORS(success, "Failed on open.");
 
@@ -333,12 +332,7 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions& opts
   // Need to know whether we'll be creating gather mesh later, to make sure we allocate enough space
   // in one shot
   bool create_gathers = false;
-  int proc_rank = 0;
-#ifdef USE_MPI
-  if (isParallel)
-    proc_rank = myPcomm->proc_config().proc_rank();
-#endif
-  if (proc_rank == gatherSetRank)
+  if (rank == gatherSetRank)
     create_gathers = true;
 
   // compute the number of local quads, accounting for coarse or fine representation
@@ -582,7 +576,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>& var_n
     for (unsigned int i = 0; i < vdatas.size(); i++) {
       vdatas[i].varTags.resize(tstep_nums.size(), 0);
       vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readDims.resize(tstep_nums.size());
+      vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
@@ -590,13 +584,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>& var_n
           && (vsetdatas[i].varDims.size() != 1)) {
         vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
         vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readDims.resize(tstep_nums.size());
+        vsetdatas[i].readStarts.resize(tstep_nums.size());
         vsetdatas[i].readCounts.resize(tstep_nums.size());
       }
       else {
         vsetdatas[i].varTags.resize(1, 0);
         vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readDims.resize(1);
+        vsetdatas[i].readStarts.resize(1);
         vsetdatas[i].readCounts.resize(1);
       }
     }
@@ -657,12 +651,12 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(EntityHandle file_
 
       // Set up the dimensions and counts
       // First: time
-      vdatas[i].readDims[t].push_back(tstep_nums[t]);
+      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
       vdatas[i].readCounts[t].push_back(1);
 
       // Next: numLev
       if (vdatas[i].numLev != 1) {
-        vdatas[i].readDims[t].push_back(0);
+        vdatas[i].readStarts[t].push_back(0);
         vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
       }
 
@@ -672,9 +666,9 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(EntityHandle file_
           // vertices
           // we will start from the first localGid, actually; we will reset that
           // later on, anyway, in a loop
-          vdatas[i].readDims[t].push_back(localGid[0] - 1);
+          vdatas[i].readStarts[t].push_back(localGid[0] - 1);
           vdatas[i].readCounts[t].push_back(localGid.size());
-          assert(vdatas[i].readDims[t].size() == vdatas[i].varDims.size());
+          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
           range = &verts;
           break;
         default:
@@ -744,7 +738,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle file_set
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
           // assume that the last dimension is for the ncol,
           // node varying variable
 
@@ -755,13 +749,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle file_set
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readDims[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
 
             // do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCAG2(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpdoubledata[indexInDoubleArray]) NCREQ2);
             ERRORS(success, "Failed to read double data in loop");
             // we need to increment the index in double array for the
@@ -791,7 +785,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle file_set
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
           // assume that the last dimension is for the ncol,
           // node varying variable
 
@@ -802,13 +796,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle file_set
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readDims[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
 
             // do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCAG2(_vara_float)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpfloatdata[indexInFloatArray]) NCREQ2);
             ERRORS(success, "Failed to read float data in loop");
             // we need to increment the index in float array for the
@@ -888,17 +882,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         case NC_CHAR: {
-          std::vector<char> tmpchardata(sz);
-          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readDims[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]);
-          else {
-            for (std::size_t idx = 0; idx != tmpchardata.size(); idx++)
-              ((char*) data)[idx] = tmpchardata[idx];
-          }
-          ERRORS(success, "Failed to read char data.");
+          ERRORR(MB_FAILURE, "not implemented");
           break;
         }
         case NC_DOUBLE: {
@@ -910,7 +894,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
 
           // Assume that the last dimension is for the ncol
           size_t indexInDoubleArray = 0;
@@ -920,11 +904,11 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readDims[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpdoubledata[indexInDoubleArray]) NCREQ);
             ERRORS(success, "Failed to read float data in loop");
             // We need to increment the index in double array for the
@@ -935,7 +919,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
 
           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]);
+            success = _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpdoubledata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
               ((double*) data)[idx] = tmpdoubledata[idx];
@@ -951,7 +935,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
 
           // Assume that the last dimension is for the ncol
           size_t indexInFloatArray = 0;
@@ -961,11 +945,11 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readDims[t][nbDims-1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims-1] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims-1] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpfloatdata[indexInFloatArray]) NCREQ);
             ERRORS(success, "Failed to read float data in loop");
             // We need to increment the index in float array for the
@@ -976,7 +960,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
 
           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 = _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpfloatdata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpfloatdata.size(); idx++)
               ((float*) data)[idx] = tmpfloatdata[idx];
@@ -985,31 +969,11 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set, std:
           break;
         }
         case NC_INT: {
-          std::vector<int> tmpintdata(sz);
-          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
-              &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]);
-          else {
-            for (std::size_t idx = 0; idx != tmpintdata.size(); idx++)
-              ((int*) data)[idx] = tmpintdata[idx];
-          }
-          ERRORS(success, "Failed to read int data.");
+          ERRORR(MB_FAILURE, "not implemented");
           break;
         }
         case NC_SHORT: {
-          std::vector<short> tmpshortdata(sz);
-          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
-              &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]);
-          else {
-            for (std::size_t idx = 0; idx != tmpshortdata.size(); idx++)
-              ((short*) data)[idx] = tmpshortdata[idx];
-          }
-          ERRORS(success, "Failed to read short data.");
+          ERRORR(MB_FAILURE, "not implemented");
           break;
         }
         default:

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 24b7241..469a89d 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -155,10 +155,10 @@ ErrorCode NCHelperMPAS::init_mesh_vals(const FileOptions& opts, EntityHandle fil
   int verticesOnEdgeVarId;
   int success = NCFUNC(inq_varid)(_fileId, "verticesOnEdge", &verticesOnEdgeVarId);
   ERRORS(success, "Failed to get variable id of verticesOnEdge.");
-  NCDF_SIZE tmp_dims[2] = {0, 0};
+  NCDF_SIZE tmp_starts[2] = {0, 0};
   NCDF_SIZE tmp_counts[2] = {static_cast<size_t>(nEdges), 2};
   verticesOnEdge.resize(nEdges * 2);
-  success = NCFUNCAG(_vara_int)(_fileId, verticesOnEdgeVarId, tmp_dims, tmp_counts, &verticesOnEdge[0] NCREQ);
+  success = NCFUNCAG(_vara_int)(_fileId, verticesOnEdgeVarId, tmp_starts, tmp_counts, &verticesOnEdge[0] NCREQ);
   ERRORS(success, "Failed to read variable values of verticesOnEdge.");
 
   // Determine the entity location type of a variable
@@ -277,23 +277,14 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi, const FileOptions& opts,
   Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
   const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
   bool& isParallel = _readNC->isParallel;
-#ifdef USE_MPI
-  ParallelComm*& myPcomm = _readNC->myPcomm;
-#endif
 
-  int rank, procs;
-#ifdef PNETCDF_FILE
+  int rank = 0, procs = 1;
+#ifdef USE_MPI
   if (isParallel) {
+    ParallelComm*& myPcomm = _readNC->myPcomm;
     rank = myPcomm->proc_config().proc_rank();
     procs = myPcomm->proc_config().proc_size();
   }
-  else {
-    rank = 0;
-    procs = 1;
-  }
-#else
-  rank = 0;
-  procs = 1;
 #endif
 
   ErrorCode rval;
@@ -559,7 +550,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
     for (unsigned int i = 0; i < vdatas.size(); i++) {
       vdatas[i].varTags.resize(tstep_nums.size(), 0);
       vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readDims.resize(tstep_nums.size());
+      vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
@@ -567,13 +558,13 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
           && (vsetdatas[i].varDims.size() != 1)) {
         vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
         vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readDims.resize(tstep_nums.size());
+        vsetdatas[i].readStarts.resize(tstep_nums.size());
         vsetdatas[i].readCounts.resize(tstep_nums.size());
       }
       else {
         vsetdatas[i].varTags.resize(1, 0);
         vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readDims.resize(1);
+        vsetdatas[i].readStarts.resize(1);
         vsetdatas[i].readCounts.resize(1);
       }
     }
@@ -655,26 +646,26 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(EntityHandle file_s
 
       // Set up the dimensions and counts
       // First: Time
-      vdatas[i].readDims[t].push_back(tstep_nums[t]);
+      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
       vdatas[i].readCounts[t].push_back(1);
 
       // Next: nCells or nEdges or nVertices
       switch (vdatas[i].entLoc) {
         case ReadNC::ENTLOCVERT:
           // vertices
-          vdatas[i].readDims[t].push_back(localGidVerts[0] - 1);
+          vdatas[i].readStarts[t].push_back(localGidVerts[0] - 1);
           vdatas[i].readCounts[t].push_back(nLocalVertices);
           range = &verts;
           break;
         case ReadNC::ENTLOCFACE:
           // faces
-          vdatas[i].readDims[t].push_back(localGidCells[0] - 1);
+          vdatas[i].readStarts[t].push_back(localGidCells[0] - 1);
           vdatas[i].readCounts[t].push_back(nLocalCells);
           range = &facesOwned;
           break;
         case ReadNC::ENTLOCEDGE:
           // edges
-          vdatas[i].readDims[t].push_back(localGidEdges[0] - 1);
+          vdatas[i].readStarts[t].push_back(localGidEdges[0] - 1);
           vdatas[i].readCounts[t].push_back(nLocalEdges);
           range = &edges;
           break;
@@ -684,9 +675,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(EntityHandle file_s
       }
 
       // Last, numLev, even if it is 1
-      vdatas[i].readDims[t].push_back(0);
+      vdatas[i].readStarts[t].push_back(0);
       vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-      assert(vdatas[i].readDims[t].size() == vdatas[i].varDims.size());
+      assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
 
       // Get ptr to tag space
       if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1)
@@ -766,7 +757,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(EntityHandle file_set,
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
 
           // Assume that the last dimension is for the nVertLevels
           size_t indexInDoubleArray = 0;
@@ -776,13 +767,13 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(EntityHandle file_set,
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readDims[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims - 2] = (NCDF_SIZE) (endh - starth + 1);
 
             // do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCAG2(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpdoubledata[indexInDoubleArray]) NCREQ2);
             ERRORS(success, "Failed to read double data in loop");
             // we need to increment the index in double array for the
@@ -909,7 +900,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(EntityHandle file_set, std::
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readDims[t].size();
+          size_t nbDims = vdatas[i].readStarts[t].size();
 
           // Assume that the last dimension is for the nVertLevels
           size_t indexInDoubleArray = 0;
@@ -919,11 +910,11 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(EntityHandle file_set, std::
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readDims[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readStarts[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
             vdatas[i].readCounts[t][nbDims - 2] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
                             &(tmpdoubledata[indexInDoubleArray]) NCREQ);
             ERRORS(success, "Failed to read double data in loop");
             // We need to increment the index in double array for the

diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index abe690f..4efabab 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -127,7 +127,7 @@ private:
     std::string varName;
     std::vector<Tag> varTags; // One tag for each time step, varTags[t]
     std::vector<void*> varDatas;
-    std::vector<std::vector<NCDF_SIZE> > readDims; // Start value for this [t][dim]
+    std::vector<std::vector<NCDF_SIZE> > readStarts; // Start value for this [t][dim]
     std::vector<std::vector<NCDF_SIZE> > readCounts; // Number of data values for this [t][dim]
     int entLoc;
     int numLev;

diff --git a/src/io/mhdf/include/mhdf.h b/src/io/mhdf/include/mhdf.h
index 9a7a478..db36d63 100644
--- a/src/io/mhdf/include/mhdf.h
+++ b/src/io/mhdf/include/mhdf.h
@@ -70,7 +70,7 @@ extern "C" {
  * type of sufficient size to accomodate the entity IDs.  
  *
  * The \c tstt group contains four sub-groups, a datatype object, and a 
- * dataset object.  The three sub-groups are: \c nodes, \c elements, 
+ * dataset object.  The four sub-groups are: \c nodes, \c elements,
  * \c sets, and \c tags.  The dataset is named \c history .
  *
  * The \c elemtypes datatype is an enumeration of the elem topologies

diff --git a/src/parallel/ParallelComm.cpp b/src/parallel/ParallelComm.cpp
index 348bad0..90bab23 100644
--- a/src/parallel/ParallelComm.cpp
+++ b/src/parallel/ParallelComm.cpp
@@ -6894,12 +6894,10 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
   
     // take all shared entities if incoming list is empty
     Range entities;
-    if (entities_in.empty()) {
+    if (entities_in.empty()) 
       std::copy(sharedEnts.begin(), sharedEnts.end(), range_inserter(entities));
-    }
-    else 
-      entities = entities_in;
-  
+    else entities = entities_in;
+
     int dum_ack_buff;
 
     for (ind = 0, sit = buffProcs.begin(); sit != buffProcs.end(); sit++, ind++) {
@@ -6910,7 +6908,7 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
       result = filter_pstatus(tag_ents, PSTATUS_SHARED, PSTATUS_AND, *sit);
       RRA("Failed pstatus AND check.");
     
-      // remote nonowned entities
+      // remove nonowned entities
       if (!tag_ents.empty()) {
         result = filter_pstatus(tag_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT);
         RRA("Failed pstatus NOT check.");
@@ -6998,7 +6996,10 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
     assert(src_tags.size() == dst_tags.size());
     if (src_tags != dst_tags) {
       std::vector<unsigned char> data;
-      Range owned_ents(entities_in);
+      Range owned_ents;
+      if (entities_in.empty()) 
+        std::copy(sharedEnts.begin(), sharedEnts.end(), range_inserter(entities));
+      else owned_ents = entities_in;
       result = filter_pstatus(owned_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT);
       RRA("Failure to get subset of owned entities");
   

diff --git a/src/parallel/moab/ParallelComm.hpp b/src/parallel/moab/ParallelComm.hpp
index c558334..55bdd93 100644
--- a/src/parallel/moab/ParallelComm.hpp
+++ b/src/parallel/moab/ParallelComm.hpp
@@ -291,26 +291,38 @@ namespace moab {
     /** \brief Exchange tags for all shared and ghosted entities
      * This function should be called collectively over the communicator for this ParallelComm.
      * If this version is called, all ghosted/shared entities should have a value for this
-     * tag (or the tag should have a default value).
-     * \param tags Vector of tag handles to be exchanged
+     * tag (or the tag should have a default value).  If the entities vector is empty, all shared entities
+     * participate in the exchange.  If a proc has no owned entities this function must still be called
+     * since it is collective.
+     * \param src_tags Vector of tag handles to be exchanged
+     * \param dst_tags Tag handles to store the tags on the non-owning procs
+     * \param entities Entities for which tags are exchanged
      */
     ErrorCode exchange_tags( const std::vector<Tag> &src_tags,
-			     const  std::vector<Tag> &dst_tags,
-			     const Range &entities);
+                             const  std::vector<Tag> &dst_tags,
+                             const Range &entities);
   
     /** \brief Exchange tags for all shared and ghosted entities
-     * This function should be called collectively over the communicator for this ParallelComm
+     * This function should be called collectively over the communicator for this ParallelComm.
+     * If the entities vector is empty, all shared entities
+     * participate in the exchange.  If a proc has no owned entities this function must still be called
+     * since it is collective.
      * \param tag_name Name of tag to be exchanged
+     * \param entities Entities for which tags are exchanged
      */
     ErrorCode exchange_tags( const char *tag_name,
-			     const Range &entities);
+                             const Range &entities);
   
     /** \brief Exchange tags for all shared and ghosted entities
-     * This function should be called collectively over the communicator for this ParallelComm
+     * This function should be called collectively over the communicator for this ParallelComm.  
+     * If the entities vector is empty, all shared entities
+     * participate in the exchange.  If a proc has no owned entities this function must still be called
+     * since it is collective.
      * \param tagh Handle of tag to be exchanged
+     * \param entities Entities for which tags are exchanged
      */
     ErrorCode exchange_tags( Tag tagh,
-			     const Range &entities);
+                             const Range &entities);
   
     /** \brief Perform data reduction operation for all shared and ghosted entities
      * This function should be called collectively over the communicator for this ParallelComm.

diff --git a/test/io/read_nc.cpp b/test/io/read_nc.cpp
index caff6a4..0e9adf8 100644
--- a/test/io/read_nc.cpp
+++ b/test/io/read_nc.cpp
@@ -120,7 +120,7 @@ void test_read_eul_onevar()
 #endif
 
   const double eps = 0.0001;
-  double val[4 * 26];
+  double val[8 * 26];
 
   if (1 == procs) {
     Range global_quads;
@@ -128,13 +128,18 @@ void test_read_eul_onevar()
     CHECK_ERR(rval);
     CHECK_EQUAL((size_t)4608, global_quads.size());
 
-    EntityHandle gloabl_quad_ents[] = {global_quads[0], global_quads[4559], global_quads[48], global_quads[4607]};
-    rval = mb.tag_get_data(Ttag0, &gloabl_quad_ents[0], 4, val);
-
-    CHECK_REAL_EQUAL(252.8529, val[0], eps); // First global quad
-    CHECK_REAL_EQUAL(205.3905, val[26], eps); // 4660th global quad
-    CHECK_REAL_EQUAL(252.7116, val[52], eps); // 49th global quad
-    CHECK_REAL_EQUAL(200.6828, val[78], eps); // Last global quad
+    EntityHandle gloabl_quad_ents[] = {global_quads[0], global_quads[2255], global_quads[2304], global_quads[4559],
+                                       global_quads[48], global_quads[2303], global_quads[2352], global_quads[4607]};
+    rval = mb.tag_get_data(Ttag0, &gloabl_quad_ents[0], 8, val);
+
+    CHECK_REAL_EQUAL(252.8529, val[0 * 26], eps); // First global quad
+    CHECK_REAL_EQUAL(234.8390, val[1 * 26], eps); // 2256th global quad
+    CHECK_REAL_EQUAL(232.6458, val[2 * 26], eps); // 2305th global quad
+    CHECK_REAL_EQUAL(205.3905, val[3 * 26], eps); // 4560th global quad
+    CHECK_REAL_EQUAL(252.7116, val[4 * 26], eps); // 49th global quad
+    CHECK_REAL_EQUAL(232.6670, val[5 * 26], eps); // 2304th global quad
+    CHECK_REAL_EQUAL(234.6922, val[6 * 26], eps); // 2353th global quad
+    CHECK_REAL_EQUAL(200.6828, val[7 * 26], eps); // Last global quad
   }
   else if (2 == procs) {
     Range local_quads;
@@ -142,16 +147,20 @@ void test_read_eul_onevar()
     CHECK_ERR(rval);
     CHECK_EQUAL((size_t)2304, local_quads.size());
 
-    EntityHandle local_quad_ents[] = {local_quads[0], local_quads[2303]};
-    rval = mb.tag_get_data(Ttag0, &local_quad_ents[0], 2, val);
+    EntityHandle local_quad_ents[] = {local_quads[0], local_quads[1151], local_quads[1152], local_quads[2303]};
+    rval = mb.tag_get_data(Ttag0, &local_quad_ents[0], 4, val);
 
     if (0 == rank) {
-      CHECK_REAL_EQUAL(252.8529, val[0], eps); // First local quad, first global quad
-      CHECK_REAL_EQUAL(205.3905, val[26], eps); // Last local quad, 4660th global quad
+      CHECK_REAL_EQUAL(252.8529, val[0 * 26], eps); // First local quad, first global quad
+      CHECK_REAL_EQUAL(234.8390, val[1 * 26], eps); // Median local quad, 2256th global quad
+      CHECK_REAL_EQUAL(232.6458, val[2 * 26], eps); // Median local quad, 2305th global quad
+      CHECK_REAL_EQUAL(205.3905, val[3 * 26], eps); // Last local quad, 4560th global quad
     }
     else if (1 == rank) {
-      CHECK_REAL_EQUAL(252.7116, val[0], eps); // First local quad, 49th global quad
-      CHECK_REAL_EQUAL(200.6828, val[26], eps); // Last local quad, last global quad
+      CHECK_REAL_EQUAL(252.7116, val[0 * 26], eps); // First local quad, 49th global quad
+      CHECK_REAL_EQUAL(232.6670, val[1 * 26], eps); // Median local quad, 2304th global quad
+      CHECK_REAL_EQUAL(234.6922, val[2 * 26], eps); // Median local quad, 2353th global quad
+      CHECK_REAL_EQUAL(200.6828, val[3 * 26], eps); // Last local quad, last global quad
     }
   }
 }
@@ -303,6 +312,60 @@ void test_read_fv_onevar()
 
   rval = mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
   CHECK_ERR(rval);
+
+  // Check values of tag T0 (first level) at some strategically chosen places below
+  int rank = 0;
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  rank = pcomm->proc_config().proc_rank();
+  procs = pcomm->proc_config().proc_size();
+#endif
+
+  const double eps = 0.0001;
+  double val[8 * 26];
+
+  if (1 == procs) {
+    Range global_quads;
+    rval = mb.get_entities_by_type(0, MBQUAD, global_quads);
+    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)3312, global_quads.size());
+
+    EntityHandle gloabl_quad_ents[] = {global_quads[0], global_quads[1619], global_quads[1656], global_quads[3275],
+                                       global_quads[36], global_quads[1655], global_quads[1692], global_quads[3311]};
+    rval = mb.tag_get_data(Ttag0, &gloabl_quad_ents[0], 8, val);
+
+    CHECK_REAL_EQUAL(253.6048, val[0 * 26], eps); // First global quad
+    CHECK_REAL_EQUAL(232.2170, val[1 * 26], eps); // 1620th global quad
+    CHECK_REAL_EQUAL(232.7454, val[2 * 26], eps); // 1657th global quad
+    CHECK_REAL_EQUAL(210.2581, val[3 * 26], eps); // 3276th global quad
+    CHECK_REAL_EQUAL(253.6048, val[4 * 26], eps); // 37th global quad
+    CHECK_REAL_EQUAL(232.9553, val[5 * 26], eps); // 1656th global quad
+    CHECK_REAL_EQUAL(232.1704, val[6 * 26], eps); // 1693th global quad
+    CHECK_REAL_EQUAL(210.2581, val[7 * 26], eps); // Last global quad
+  }
+  else if (2 == procs) {
+    Range local_quads;
+    rval = mb.get_entities_by_type(0, MBQUAD, local_quads);
+    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)1656, local_quads.size());
+
+    EntityHandle local_quad_ents[] = {local_quads[0], local_quads[827], local_quads[828], local_quads[1655]};
+    rval = mb.tag_get_data(Ttag0, &local_quad_ents[0], 4, val);
+
+    if (0 == rank) {
+      CHECK_REAL_EQUAL(253.6048, val[0 * 26], eps); // First local quad, first global quad
+      CHECK_REAL_EQUAL(232.2170, val[1 * 26], eps); // Median local quad, 1620th global quad
+      CHECK_REAL_EQUAL(232.7454, val[2 * 26], eps); // Median local quad, 1657th global quad
+      CHECK_REAL_EQUAL(210.2581, val[3 * 26], eps); // Last local quad, 3276th global quad
+    }
+    else if (1 == rank) {
+      CHECK_REAL_EQUAL(253.6048, val[0 * 26], eps); // First local quad, 37th global quad
+      CHECK_REAL_EQUAL(232.9553, val[1 * 26], eps); // Median local quad, 1656th global quad
+      CHECK_REAL_EQUAL(232.1704, val[2 * 26], eps); // Median local quad, 1693th global quad
+      CHECK_REAL_EQUAL(210.2581, val[3 * 26], eps); // Last local quad, last global quad
+    }
+  }
 }
 
 void test_read_fv_onetimestep()

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/12c88eda3f02/
Changeset:   12c88eda3f02
Branch:      None
User:        danwu
Date:        2013-08-02 17:28:20
Summary:     Merged fathomteam/moab into master
Affected #:  1 file

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 0a7802f..16a2348 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -278,11 +278,11 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions& opts
 
 #ifdef PNETCDF_FILE
   if (isParallel) {
+    ParallelComm*& myPcomm = _readNC->myPcomm;
     success = NCFUNC(open)(myPcomm->proc_config().proc_comm(), conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
   }
-  else {
+  else
     success = NCFUNC(open)(MPI_COMM_SELF, conn_fname.c_str(), 0, MPI_INFO_NULL, &connectId);
-  }
 #else
   success = NCFUNC(open)(conn_fname.c_str(), 0, &connectId);
 #endif


https://bitbucket.org/fathomteam/moab/commits/e13aafc82d82/
Changeset:   e13aafc82d82
Branch:      None
User:        danwu
Date:        2013-08-29 21:37:04
Summary:     Merged fathomteam/moab into master
Affected #:  51 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/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
index 8f81cff..84aaf87 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.
@@ -699,7 +699,7 @@ dimension.
 <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

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/user.dox.in b/doc/user.dox.in
index 07f707f..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 

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/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/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 8084640..054b8dd 100644
--- a/src/ScdInterface.cpp
+++ b/src/ScdInterface.cpp
@@ -20,7 +20,9 @@
         
 namespace moab 
 {
-    
+
+const char *ScdParData::PartitionMethodNames[] = {"alljorkori", "alljkbal", "sqij", "sqjk", "sqijk", "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/Skinner.cpp b/src/Skinner.cpp
index 5869777..57b3d51 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,
@@ -264,7 +265,8 @@ ErrorCode Skinner::find_skin( const Range& source_entities,
     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, 
+    return find_skin_vertices( meshset,
+                               source_entities,
                                get_vertices ? &output_handles : 0,
                                get_vertices ? 0 : &output_handles,
                                output_reverse_handles,
@@ -276,7 +278,7 @@ ErrorCode Skinner::find_skin( const Range& source_entities,
   if (!source_entities.all_of_dimension(d))
     return MB_TYPE_OUT_OF_RANGE;
   
-  rval = thisMB->get_entities_by_dimension( 0, d-1, prev );
+  rval = thisMB->get_entities_by_dimension( meshset, d-1, prev );
   if (MB_SUCCESS != rval)
     return rval;
   
@@ -297,7 +299,7 @@ ErrorCode Skinner::find_skin( const Range& source_entities,
   
   if (!create_skin_elements) {
     Range new_skin;
-    rval = thisMB->get_entities_by_dimension( 0, d-1, new_skin);
+    rval = thisMB->get_entities_by_dimension( meshset, d-1, new_skin);
     if (MB_SUCCESS != rval)
       return rval;
     new_skin = subtract( new_skin, prev );
@@ -1062,13 +1064,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 +1089,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 +1108,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 d28c824..b013472 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,11 @@ 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];
 
@@ -159,28 +326,28 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
         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:
@@ -194,11 +361,6 @@ ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vector<Read
     }
   }
 
-#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]);
@@ -209,7 +371,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 +382,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 +476,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 = 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 = 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());
+  }
+  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 +791,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 +809,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 +828,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 +854,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 +865,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 +884,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 +907,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 +915,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 +936,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 +976,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 +1008,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 +1069,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 +1098,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 +1111,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 +1137,19 @@ 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];
@@ -738,10 +1160,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         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 = _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];
@@ -752,10 +1174,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         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 = _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];
@@ -766,10 +1188,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         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 = _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];
@@ -780,10 +1202,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         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 = _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];
@@ -794,10 +1216,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
         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 = _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];
@@ -814,11 +1236,6 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, std::v
     }
   }
 
-#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]);
@@ -827,7 +1244,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 +1255,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 +1324,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.");
   }

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/4410fda073aa/
Changeset:   4410fda073aa
Branch:      None
User:        danwu
Date:        2013-09-10 23:14:34
Summary:     Merged fathomteam/moab into master
Affected #:  39 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/README b/README
index 6bcf434..563265c 100644
--- a/README
+++ b/README
@@ -82,4 +82,3 @@ Implementation:
 2.00 (11/1/06): LOTS of bug fixes & improvements
 1.00 (2/1/04): Initial release
 
-

diff --git a/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
index 84aaf87..d67ca27 100644
--- a/doc/MetaData/metadata.h
+++ b/doc/MetaData/metadata.h
@@ -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,24 +683,37 @@ 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 
@@ -702,11 +721,10 @@ dimension.
 <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/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/ScdInterface.cpp b/src/ScdInterface.cpp
index 054b8dd..1441e51 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"
@@ -23,7 +24,7 @@ namespace moab
 
 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_ents && !assign_gids) assign_gids = true; // need to assign gids in order to tag shared verts
+#else
+  if (par_data && low == high && ScdParData::NOPART != par_data->partMethod) {
+      // requesting creation of parallel mesh, so need to compute partition
+    if (!par_data->pComm) {
+        // this is a really boneheaded way to have to create a PC
+      par_data->pComm = ParallelComm::get_pcomm(mbImpl, 0);
+      if (NULL == par_data->pComm) par_data->pComm = new ParallelComm(mbImpl, MPI_COMM_WORLD);
+    }
+    int ldims[6];
+    rval = compute_partition(par_data->pComm->size(), par_data->pComm->rank(), *par_data, 
+                             ldims, tmp_lper, par_data->pDims);
+    ERRORR(rval, "Error returned from compute_partition.");
+    low.set(ldims);
+    high.set(ldims+3);
+    if (par_data->pComm->get_debug_verbosity() > 0) {
+      std::cout << "Proc " << par_data->pComm->rank() << ": " << *par_data;
+      std::cout << "Proc " << par_data->pComm->rank() << " local dims: " 
+                << low << "-" << high << std::endl;
+    }
+  }
+#endif
+  
   HomCoord tmp_size = high - low + HomCoord(1, 1, 1, 0);
   if ((tmp_size[1] && num_coords && (int)num_coords < tmp_size[0]) ||
       (tmp_size[2] && num_coords && (int)num_coords < tmp_size[0]*tmp_size[1]))
@@ -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;
@@ -690,7 +753,7 @@ ErrorCode ScdInterface::get_neighbor_alljkbal(int np, int pfrom,
   pto = -1;
   across_bdy[0] = across_bdy[1] = across_bdy[2] = 0;
   
-  int ldims[6], pijk[3], lperiodic[2];
+  int ldims[6], pijk[3], lperiodic[3];
   ErrorCode rval = compute_partition_alljkbal(np, pfrom, gdims, gperiodic, 
                                               ldims, lperiodic, pijk);
   if (MB_SUCCESS != rval) return rval;
@@ -1087,7 +1150,7 @@ ErrorCode ScdInterface::get_neighbor_alljorkori(int np, int pfrom,
   pto = -1;
   if (np == 1) return MB_SUCCESS;
   
-  int pijk[3], lperiodic[2], ldims[6];
+  int pijk[3], lperiodic[3], ldims[6];
   rval = compute_partition_alljorkori(np, pfrom, gdims, gperiodic, ldims, lperiodic, pijk);
   if (MB_SUCCESS != rval) return rval;
 

diff --git a/src/Skinner.cpp b/src/Skinner.cpp
index 57b3d51..b5fd24e 100644
--- a/src/Skinner.cpp
+++ b/src/Skinner.cpp
@@ -264,66 +264,13 @@ ErrorCode Skinner::find_skin( const EntityHandle meshset,
       !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( meshset,
-                               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( meshset, 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( meshset, 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,

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index b013472..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);
@@ -687,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;
@@ -706,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
@@ -736,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]]);
           }
         }
       }
@@ -813,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;
@@ -820,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);
@@ -833,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) ()
@@ -866,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++;
       }
     }
   }
@@ -1011,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;
@@ -1061,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) {

diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 6355141..4982b4c 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -164,10 +164,10 @@ protected:
   //! Center dimension numbers for i/j
   int iCDim, jCDim;
 
-  //! Whether mesh is locally periodic in i or j
+  //! Whether mesh is locally periodic in i or j or k
   int locallyPeriodic[3];
 
-  //! Whether mesh is globally periodic in i or j
+  //! Whether mesh is globally periodic in i or j or k
   int globallyPeriodic[3];
 };
 

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 98aa9c6..f883bd7 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -59,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;
@@ -75,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())
@@ -84,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;
@@ -98,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;
@@ -569,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;
@@ -595,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) {

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index c78956c..45d1b00 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -37,7 +37,7 @@ bool NCHelperMPAS::can_read_file(ReadNC* readNC)
 ErrorCode NCHelperMPAS::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;
@@ -47,7 +47,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
   // Get max edges per cell
   if ((vit = std::find(dimNames.begin(), dimNames.end(), "maxEdges")) != dimNames.end()) {
     idx = vit - dimNames.begin();
-    maxCellEdges = dimVals[idx];
+    maxCellEdges = dimLens[idx];
     if (maxCellEdges > MAX_EDGES_PER_CELL) {
       ERRORR(MB_FAILURE, "maxEdges read from MPAS file has exceeded the limit");
     }
@@ -62,7 +62,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     ERRORR(MB_FAILURE, "Couldn't find 'Time' or 'time' dimension.");
   }
   tDim = idx;
-  nTimeSteps = dimVals[idx];
+  nTimeSteps = dimLens[idx];
 
   // Get number of cells
   if ((vit = std::find(dimNames.begin(), dimNames.end(), "nCells")) != dimNames.end())
@@ -71,7 +71,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     ERRORR(MB_FAILURE, "Couldn't find 'nCells' dimension.");
   }
   cDim = idx;
-  nCells = dimVals[idx];
+  nCells = dimLens[idx];
 
   // Get number of edges
   if ((vit = std::find(dimNames.begin(), dimNames.end(), "nEdges")) != dimNames.end())
@@ -80,7 +80,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     ERRORR(MB_FAILURE, "Couldn't find 'nEdges' dimension.");
   }
   eDim = idx;
-  nEdges = dimVals[idx];
+  nEdges = dimLens[idx];
 
   // Get number of vertices
   vDim = -1;
@@ -90,7 +90,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     ERRORR(MB_FAILURE, "Couldn't find 'nVertices' dimension.");
   }
   vDim = idx;
-  nVertices = dimVals[idx];
+  nVertices = dimLens[idx];
 
   // Get number of levels
   if ((vit = std::find(dimNames.begin(), dimNames.end(), "nVertLevels")) != dimNames.end())
@@ -99,7 +99,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     ERRORR(MB_FAILURE, "Couldn't find 'nVertLevels' dimension.");
   }
   levDim = idx;
-  nLevels = dimVals[idx];
+  nLevels = dimLens[idx];
 
   // Store xVertex values in xVertVals
   std::map<std::string, ReadNC::VarData>::iterator vmit;
@@ -697,7 +697,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
 ErrorCode NCHelperMPAS::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;
@@ -747,7 +747,7 @@ ErrorCode NCHelperMPAS::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) {

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index eee8a9e..50225df 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -294,9 +294,9 @@ ErrorCode ReadNC::read_header()
   dbgOut.tprintf(1, "Read %u attributes\n", (unsigned int) globalAtts.size());
 
   // Read in dimensions into dimVals
-  result = get_dimensions(fileId, dimNames, dimVals);
+  result = get_dimensions(fileId, dimNames, dimLens);
   ERRORR(result, "Getting dimensions.");
-  dbgOut.tprintf(1, "Read %u dimensions\n", (unsigned int) dimVals.size());
+  dbgOut.tprintf(1, "Read %u dimensions\n", (unsigned int) dimNames.size());
 
   // Read in variables into varInfo
   result = get_variables();
@@ -328,7 +328,7 @@ ErrorCode ReadNC::get_attributes(int var_id, int num_atts, std::map<std::string,
   return MB_SUCCESS;
 }
 
-ErrorCode ReadNC::get_dimensions(int file_id, std::vector<std::string>& dim_names, std::vector<int>& dim_vals)
+ErrorCode ReadNC::get_dimensions(int file_id, std::vector<std::string>& dim_names, std::vector<int>& dim_lens)
 {
   // Get the number of dimensions
   int num_dims;
@@ -341,18 +341,18 @@ ErrorCode ReadNC::get_dimensions(int file_id, std::vector<std::string>& dim_name
   }
 
   char dim_name[NC_MAX_NAME + 1];
-  NCDF_SIZE dum_len;
+  NCDF_SIZE dim_len;
   dim_names.resize(num_dims);
-  dim_vals.resize(num_dims);
+  dim_lens.resize(num_dims);
 
   for (int i = 0; i < num_dims; i++) {
-    success = NCFUNC(inq_dim)(file_id, i, dim_name, &dum_len);
+    success = NCFUNC(inq_dim)(file_id, i, dim_name, &dim_len);
     ERRORS(success, "Trouble getting dimension info.");
 
-    dim_vals[i] = dum_len;
     dim_names[i] = std::string(dim_name);
+    dim_lens[i] = dim_len;
 
-    dbgOut.tprintf(2, "Dimension %s, length=%u\n", dim_name, (unsigned int) dum_len);
+    dbgOut.tprintf(2, "Dimension %s, length=%u\n", dim_name, (unsigned int) dim_len);
   }
 
   return MB_SUCCESS;
@@ -367,7 +367,7 @@ ErrorCode ReadNC::get_variables()
 
   int ntimes = 0;
   if (vit != dimNames.end())
-    ntimes = dimVals[vit - dimNames.begin()];
+    ntimes = dimLens[vit - dimNames.begin()];
   if (!ntimes)
     ntimes = 1;
 

diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index 41c866a..e8b1845 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -138,7 +138,7 @@ private:
                            const char *prefix = "");
 
   //! Get all dimensions in the file
-  ErrorCode get_dimensions(int file_id, std::vector<std::string>& dim_names, std::vector<int>& dim_vals);
+  ErrorCode get_dimensions(int file_id, std::vector<std::string>& dim_names, std::vector<int>& dim_lens);
 
   //! Get the variable names and other info defined for this file
   ErrorCode get_variables();
@@ -159,15 +159,15 @@ private:
   //! File numbers assigned by netcdf
   int fileId;
 
-  //! Dimensions
+  //! Dimension names
   std::vector<std::string> dimNames;
 
+  //! Dimension lengths
+  std::vector<int> dimLens;
+
   //! These should be taken out when we fix the dummy var info things
   std::set<std::string> dummyVarNames;
 
-  //! Dimension values
-  std::vector<int> dimVals;
-
   //! Global attribs
   std::map<std::string, AttData> globalAtts;
 

diff --git a/src/moab/HomXform.hpp b/src/moab/HomXform.hpp
index 8110afa..8f3a1a7 100644
--- a/src/moab/HomXform.hpp
+++ b/src/moab/HomXform.hpp
@@ -31,6 +31,7 @@
 #define XFORM_INDEX(a,b) 4*a+b
 
 #include <math.h>
+#include <ostream>
 
 namespace moab {
 
@@ -473,6 +474,12 @@ inline int &HomCoord::operator[](const int &param)
   return homCoord[param];
 }
 
+inline std::ostream &operator<<(std::ostream &str, const HomCoord &hc)
+{
+  str << "(" << hc.i() << "," << hc.j() << "," << hc.k() << ")";
+  return str;
+}
+
 inline HomXform::HomXform(const int matrix[16]) 
 {
   for (int i = 0; i < 16; i++)

diff --git a/src/moab/ScdInterface.hpp b/src/moab/ScdInterface.hpp
index f8a4df8..df8c772 100644
--- a/src/moab/ScdInterface.hpp
+++ b/src/moab/ScdInterface.hpp
@@ -17,7 +17,6 @@ class EntitySequence;
 class ScdVertexData;
 class EntitySequence;
 class ScdBox;
-class Core;
 class ParallelComm;
 
 /** \class ScdInterface ScdInterface.hpp "moab/ScdInterface.hpp"
@@ -104,10 +103,10 @@ class ParallelComm;
       //! struct for keeping parallel data in one place
 class ScdParData {
 public:
-  ScdParData() : partMethod(NOPART) {
-    gDims[0] = gDims[1] = gDims[2] = gDims[3] = gDims[4] = gDims[5] = -1;
-    gPeriodic[0] = gPeriodic[1] = gPeriodic[2] = -1;
-    pDims[0] = pDims[1] = pDims[2] = -1;
+  ScdParData() : partMethod(NOPART), pComm(NULL) {
+    gDims[0] = gDims[1] = gDims[2] = gDims[3] = gDims[4] = gDims[5] = 0;
+    gPeriodic[0] = gPeriodic[1] = gPeriodic[2] = 0;
+    pDims[0] = pDims[1] = pDims[2] = 0;
   }
 
     //! Partition method enumeration; these strategies are described in comments for
@@ -124,12 +123,14 @@ public:
     //! lower and upper corners of global box
   int gDims[6];
 
-    //! is globally periodic in i or j
+    //! is globally periodic in i or j or k
   int gPeriodic[3];
 
     //! number of procs in each direction
   int pDims[3];
 
+    //! parallel communicator object for this par scd mesh
+  ParallelComm *pComm;
 };
   
 class ScdInterface 
@@ -145,7 +146,7 @@ public:
      * \param impl MOAB instance
      * \param find_boxes If true, search all the entity sets, caching the structured mesh blocks
      */
-  ScdInterface(Core *impl, bool find_boxes = false);
+  ScdInterface(Interface *impl, bool find_boxes = false);
   
     // Destructor
   ~ScdInterface();
@@ -165,13 +166,16 @@ public:
      * \param coords Coordinates of vertices, interleaved (xyzxyz...); if NULL, no coords are set
      * \param num_coords Number of coordinate values; if zero, no coords are set
      * \param new_box Reference to box of structured mesh
-     * \param lperiodic[2] If lperiodic[s] != 0, direction s is locally periodic
+     * \param lperiodic[3] If lperiodic[s] != 0, direction s is locally periodic
      * \param par_data If non-NULL, this will get stored on the ScdBox once created, contains info
      *                 about global parallel nature of ScdBox across procs
+     * \param assign_global_ids If true, assigns 1-based global ids to vertices using GLOBAL_ID_TAG_NAME
+     * \param resolve_shared_ents If != -1, resolves shared entities up to and including dimension equal to value
      */
   ErrorCode construct_box(HomCoord low, HomCoord high, const double * const coords, unsigned int num_coords,
                           ScdBox *& new_box, int * const lperiodic = NULL, 
-                          ScdParData * const par_data = NULL);
+                          ScdParData * const par_data = NULL,
+                          bool assign_global_ids = false, int resolve_shared_ents = -1);
 
     //! Create a structured sequence of vertices, quads, or hexes
     /** Starting handle for the sequence is available from the returned ScdBox.  
@@ -182,7 +186,7 @@ public:
      * \param type EntityType, one of MBVERTEX, MBEDGE, MBQUAD, MBHEX
      * \param starting_id Requested start id of entities
      * \param new_box Reference to the newly created box of entities
-     * \param is_periodic[2] If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1])
+     * \param is_periodic[3] If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1,2])
      */
   ErrorCode create_scd_sequence(HomCoord low, HomCoord high, EntityType type,
                                 int starting_id, ScdBox *&new_box, 
@@ -270,7 +274,7 @@ public:
      * \param rdims(6) (out) Parametric min/max of destination part
      * \param facedims(6) (out) Parametric min/max of interface between pfrom and pto; if at the max in a periodic
      *                          direction, set to global min of that direction
-     * \param across_bdy(2) (out) If across_bdy[i] is -1(1), interface with pto is across periodic lower(upper) bdy 
+     * \param across_bdy(3) (out) If across_bdy[i] is -1(1), interface with pto is across periodic lower(upper) bdy
      *                            in parameter i, 0 otherwise
      */
   static ErrorCode get_neighbor(int np, int nr, const ScdParData &spd, const int * const dijk,
@@ -281,6 +285,11 @@ public:
      */
   ErrorCode tag_shared_vertices(ParallelComm *pcomm, EntityHandle seth);
   
+    //! Tag vertices with sharing data for parallel representations
+    /** Given the ParallelComm object to use, tag the vertices shared with other processors
+     */
+  ErrorCode tag_shared_vertices(ParallelComm *pcomm, ScdBox *box);
+  
 protected:
     //! Remove the box from the list on ScdInterface
   ErrorCode remove_box(ScdBox *box);
@@ -293,7 +302,7 @@ private:
     /** \param low Lower corner parameters for this box
      * \param high Upper corner parameters for this box
      * \param scd_set Entity set created
-     * \param is_periodic[2] If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1])
+     * \param is_periodic[3] If is_periodic[s] is non-zero, mesh should be periodic in direction s (s=[0,1,2])
      */
   ErrorCode create_box_set(const HomCoord low, const HomCoord high,
                            EntityHandle &scd_set,
@@ -372,8 +381,11 @@ private:
   
   static int gtol(const int *gijk, int i, int j, int k);
 
+    //! assign global ids to vertices in this box
+  ErrorCode assign_global_ids(ScdBox *box);
+  
   //! interface instance
-  Core *mbImpl;
+  Interface *mbImpl;
 
     //! whether we've searched the database for boxes yet
   bool searchedBoxes;
@@ -619,12 +631,18 @@ public:
      */
   bool locally_periodic_k() const;
   
-    //! Return whether box is locally periodic in i and j
-    /** Return whether box is locally periodic in i and j
-     * \param lperiodic Non-zero if locally periodic in i [0] or j [1]
-     */
-  void locally_periodic(bool lperiodic[3]) const;
+    //! Set local periodicity
+    /** 
+     * \param lperiodic Vector of ijk periodicities to set this box to
+      */
+  void locally_periodic(bool lperiodic[3]);
 
+    //! Get local periodicity
+    /** 
+     * \return Vector of ijk periodicities for this box
+     */
+  const int *locally_periodic() const;
+ 
     //! Return parallel data 
     /** Return parallel data, if there is any
      * \return par_data Parallel data set on this box 
@@ -706,7 +724,7 @@ private:
     //! lower and upper corners
   int boxDims[6];
 
-    //! is locally periodic in i or j
+    //! is locally periodic in i or j or k
   int locallyPeriodic[3];
 
     //! parallel data associated with this box, if any
@@ -1120,7 +1138,8 @@ inline ErrorCode ScdInterface::compute_partition_sqijk(int np, int nr,
       }
     }
   }
-  if (perfa_best == -1 || perfb_best == -1) return MB_FAILURE;
+  if (perfa_best == -1 || perfb_best == -1) 
+    return MB_FAILURE;
 
     // VARIABLES DESCRIBING THE MESH:
     // pijk[i] = # procs in direction i
@@ -1214,6 +1233,25 @@ inline ErrorCode ScdInterface::get_neighbor(int np, int pfrom, const ScdParData
   return MB_FAILURE;
 }
 
+inline ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, EntityHandle seth) 
+{
+  ScdBox *box = get_scd_box(seth);
+  if (!box) {
+      // look for contained boxes
+    Range tmp_range;
+    ErrorCode rval = mbImpl->get_entities_by_type(seth, MBENTITYSET, tmp_range);
+    if (MB_SUCCESS != rval) return rval;
+    for (Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); rit++) {
+      box = get_scd_box(*rit);
+      if (box) break;
+    }
+  }
+  
+  if (!box) return MB_FAILURE;
+
+  return tag_shared_vertices(pcomm, box);
+}
+
 inline ScdInterface *ScdBox::sc_impl() const 
 {
   return scImpl;
@@ -1382,19 +1420,23 @@ inline bool ScdBox::locally_periodic_k() const
   return locallyPeriodic[2];
 }
 
-inline void ScdBox::locally_periodic(bool lperiodic[3]) const 
+inline void ScdBox::locally_periodic(bool lperiodic[3])
 {
-  for (int i = 0; i < 3; i++) 
-    lperiodic[i] = locallyPeriodic[i];
+   for (int i = 0; i < 3; i++) 
+    locallyPeriodic[i] = lperiodic[i];
 }
 
+inline const int *ScdBox::locally_periodic() const
+{
+  return locallyPeriodic;
+}
+ 
 inline std::ostream &operator<<(std::ostream &str, const ScdParData &pd) 
 {
-  static const char *PartitionMethodNames[] = {"NOPART", "ALLJORKORI", "ALLJKBAL", "SQIJ", "SQJK", "SQIJK"};
-  str << "Partition method = " << PartitionMethodNames[pd.partMethod] << ", gDims = (" 
+  str << "Partition method = " << ScdParData::PartitionMethodNames[pd.partMethod] << ", gDims = (" 
       << pd.gDims[0] << "," << pd.gDims[1] << "," << pd.gDims[2] << ")-(" 
       << pd.gDims[3] << "," << pd.gDims[4] << "," << pd.gDims[5] << "), gPeriodic = (" 
-      << pd.gPeriodic[0] << ", " << pd.gPeriodic[1] << "," << pd.gPeriodic[2] << "), pDims = ("
+      << pd.gPeriodic[0] << "," << pd.gPeriodic[1] << "," << pd.gPeriodic[2] << "), pDims = ("
       << pd.pDims[0] << "," << pd.pDims[1] << "," << pd.pDims[2] << ")" << std::endl;
   return str;
 }

diff --git a/src/moab/point_locater/element_maps/linear_hex_map.hpp b/src/moab/point_locater/element_maps/linear_hex_map.hpp
index 069d4c8..4b9cb77 100644
--- a/src/moab/point_locater/element_maps/linear_hex_map.hpp
+++ b/src/moab/point_locater/element_maps/linear_hex_map.hpp
@@ -36,29 +36,29 @@ class Linear_hex_map {
     //Constructor
     Linear_hex_map() {}
     //Copy constructor
-    Linear_hex_map( const Self & f ) {}
+    Linear_hex_map( const Self & /* f */ ) {}
 
  public:
     //Natural coordinates
     template< typename Moab, typename Entity_handle, 
 	      typename Points, typename Point>
-    std::pair< bool, Point> operator()( const Moab & moab,
-					const Entity_handle & h, 
+    std::pair< bool, Point> operator()( const Moab & /* moab */,
+					const Entity_handle & /* h */,
 					const Points & v, 
 					const Point & p, 
-					const double tol=1.e-6) const{
-	Point result(3, 0.0);
-	solve_inverse( p, result, v);
-	bool point_found = solve_inverse( p, result, v, tol) && 
-						is_contained( result, tol);
-	return std::make_pair( point_found, result);
+					const double tol = 1.e-6) const {
+      Point result(3, 0.0);
+      solve_inverse( p, result, v);
+      bool point_found = solve_inverse( p, result, v, tol) &&
+                is_contained( result, tol);
+      return std::make_pair( point_found, result);
     }
 
   private:
     //This is a hack to avoid a .cpp file and C++11
     //reference_points(i,j) will be a 1 or -1;
     //This should unroll..
-    inline const double reference_points( const std::size_t& i, 
+    inline double reference_points( const std::size_t& i,
           				  const std::size_t& j) const{
     const double rpts[8][3] = { { -1, -1, -1 },
                                 {  1, -1, -1 },

diff --git a/src/moab/point_locater/element_maps/linear_tet_map.hpp b/src/moab/point_locater/element_maps/linear_tet_map.hpp
index d48c63b..dedb8ed 100644
--- a/src/moab/point_locater/element_maps/linear_tet_map.hpp
+++ b/src/moab/point_locater/element_maps/linear_tet_map.hpp
@@ -18,14 +18,17 @@ class Linear_tet_map {
     //Natural coordinates
     template< typename Moab, typename Points, typename Point>
     std::pair< bool, Point> operator()( const Moab & moab,
-					const Entity_handle eh, 
+					const Entity_handle _eh,
 				        const Points & v, 
 					const Point & p, 
 					const double tol=1e-6) {
-	set_tet( eh, v); 
-	//TODO: Make sure this is correct
-	Point result = Tinv*p;
-	return std::make_pair( is_contained( result, tol), result);
+      // Remove the warning about unused parameter
+      if (NULL != &moab) {}
+
+      set_tet( _eh, v);
+      //TODO: Make sure this is correct
+      Point result = Tinv*p;
+      return std::make_pair( is_contained( result, tol), result);
     }
   
     private:

diff --git a/src/moab/point_locater/element_maps/quadratic_hex_map.hpp b/src/moab/point_locater/element_maps/quadratic_hex_map.hpp
index 1f8b84d..905b65c 100644
--- a/src/moab/point_locater/element_maps/quadratic_hex_map.hpp
+++ b/src/moab/point_locater/element_maps/quadratic_hex_map.hpp
@@ -53,22 +53,22 @@ class Quadratic_hex_map {
     //Natural coordinates
     template< typename Moab, typename Entity_handle, 
 	      typename Points, typename Point>
-    std::pair< bool, Point> operator()( const Moab & moab,
-					const Entity_handle & h, 
+    std::pair< bool, Point> operator()( const Moab & /* moab */,
+					const Entity_handle & /* h */,
 					const Points & v, 
 					const Point & p, 
-					const double tol=1.e-6) const{
-	Point result(3, 0.0);
-	bool point_found = solve_inverse( p, result, v, tol) && 
-						is_contained( result, tol);
-	return std::make_pair( point_found, result);
+					const double tol = 1.e-6) const {
+      Point result(3, 0.0);
+      bool point_found = solve_inverse( p, result, v, tol) &&
+                is_contained( result, tol);
+      return std::make_pair( point_found, result);
     }
 
   private:
     //This is a hack to avoid a .cpp file and C++11
     //reference_points(i,j) will be a 1 or -1;
     //This should unroll..
-    inline const double reference_points( const std::size_t& i, 
+    inline double reference_points( const std::size_t& i,
           				  const std::size_t& j) const{
     const double rpts[27][3] = {
     	{ -1, -1, -1 },
@@ -196,24 +196,24 @@ class Quadratic_hex_map {
     }
 
     template< typename Point, typename Points>
-    Matrix& jacobian( const Point & p, const Points & points, Matrix & J) const{
-	J = Matrix(0.0);
-	for (int i=0; i<27; i++){
- 		  const double  sh[3] = {  SH(reference_points(i,0), p[0]),
+    Matrix& jacobian( const Point & p, const Points & /* points */, Matrix & J) const {
+    J = Matrix(0.0);
+    for (int i = 0; i < 27; i++) {
+      const double sh[3] = { SH(reference_points(i,0), p[0]),
                        		           SH(reference_points(i,1), p[1]),
                        		           SH(reference_points(i,2), p[2]) };
-  		  const double dsh[3] = { DSH(reference_points(i,0), p[0]),
+ 	    const double dsh[3] = { DSH(reference_points(i,0), p[0]),
                         		  DSH(reference_points(i,1), p[1]),
                         	   	  DSH(reference_points(i,2), p[2]) };
-  	    for (int j=0; j<3; j++) {
-		// dxj/dr first column
-    		J(j,0)+=dsh[0]*sh[1]*sh[2]*reference_points(i,j); 
-    		J(j,1)+= sh[0]*dsh[1]*sh[2]*reference_points(i,j); // dxj/ds
-    		J(j,2)+= sh[0]*sh[1]*dsh[2]*reference_points(i,j); // dxj/dt
-  	    }
-	}
-	return J;
-   }
+      for (int j = 0; j < 3; j++) {
+        // dxj/dr first column
+        J(j, 0) += dsh[0]*sh[1]*sh[2]*reference_points(i, j);
+        J(j, 1) += sh[0]*dsh[1]*sh[2]*reference_points(i, j); // dxj/ds
+        J(j, 2) += sh[0]*sh[1]*dsh[2]*reference_points(i, j); // dxj/dt
+      }
+    }
+    return J;
+  }
   private:
 }; //Class Quadratic_hex_map
 

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/739aa3ab7916/
Changeset:   739aa3ab7916
Branch:      None
User:        danwu
Date:        2013-09-18 21:31:46
Summary:     Add -fstack-protector-all option for g++ and gcc in debug mode, to detect possible stack smashing bugs. If src/ScdInterface.cpp is reverted to a version before the fix for array index out of bounds, unit scdseq_test will terminate during make check, with <stack smashing detected> message.

Affected #:  1 file

diff --git a/config/compiler.m4 b/config/compiler.m4
index 6a7e2ed..ce83a5f 100644
--- a/config/compiler.m4
+++ b/config/compiler.m4
@@ -222,6 +222,14 @@ if test "xyes" = "x$enable_debug"; then
   CFLAGS="$CFLAGS -g"
   FCFLAGS="$FCFLAGS -g"
   FFLAGS="$FFLAGS -g"
+  # Add -fstack-protector-all option for g++ in debug mode
+  if test "x$cxx_compiler" = "xGNU"; then
+    CXXFLAGS="$CXXFLAGS -fstack-protector-all"
+  fi
+  # Add -fstack-protector-all option for gcc in debug mode
+  if test "x$cc_compiler" = "xGNU"; then
+    CFLAGS="$CFLAGS -fstack-protector-all"
+  fi
 fi
 if test "xyes" = "x$enable_cxx_optimize"; then
   CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG"


https://bitbucket.org/fathomteam/moab/commits/2c3fc8753e24/
Changeset:   2c3fc8753e24
Branch:      None
User:        danwu
Date:        2013-09-18 21:56:46
Summary:     Merged fathomteam/moab into master
Affected #:  150 files

diff --git a/.gitignore b/.gitignore
index 967aaa7..d3721c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,99 +1,132 @@
-MOABConfig.cmake
-moab.files
-config/test-driver
-moab.config
-moab.includes
-moab.creator*
-*.ccm
-*.cub
+*~
+*.a
 aclocal.m4
 autom4te.cache/
-config.h
-config.h.in
-config.log
-config.lt
-config.status
+bin
+bin/*
+*.ccm
 config/config.guess
 config/config.sub
 config/depcomp
+config.h
+config.h.in
 config/install-sh
 config/libtool.m4
+config.log
+config.lt
 config/ltmain.sh
+config/lt~obsolete.m4
 config/ltoptions.m4
 config/ltsugar.m4
 config/ltversion.m4
-config/lt~obsolete.m4
 config/missing
+config.status
+config/test-driver
 configure
+.cproject
+*.cub
+.deps
 doc/config.tex
 doc/dev.dox
-doc/user.dox
 doc/user/*
+doc/user.dox
 examples/examples.make
+examples/FileRead
+examples/GeomSetHierarchy
+examples/GetEntities
+examples/*.h5m
+examples/HelloMoabPar
+examples/itaps/FindConnectF
+examples/itaps/ListSetsNTagsCXX
+examples/itaps/ListSetsNTagsF90
+examples/itaps/TagIterateC
+examples/itaps/TagIterateF
+examples/KDTree
+examples/ObbTree
+examples/ReduceExchangeTags
+examples/SetsNTags
+examples/SkinMesh
+examples/SurfArea
+examples/TestExodusII
+include
+include/*
 itaps/iBase_f.h
 itaps/igeom/FBiGeom-Defs.inc
+itaps/igeom/FBiGeom_protos.h
+itaps/igeom/testgeom
+itaps/igeom/testSmooth2
+itaps/igeom/testSmoothGeom
+itaps/imesh/FindAdjacencyF90
 itaps/imesh/iMesh-Defs.inc
+itaps/imesh/iMesh_extensions_protos.h
 itaps/imesh/iMeshP_extensions_protos.h
 itaps/imesh/iMeshP_protos.h
-itaps/imesh/iMesh_extensions_protos.h
 itaps/imesh/iMesh_protos.h
+itaps/imesh/MOAB_iMesh_extensions_tests
+itaps/imesh/MOAB_iMeshP_unit_tests
+itaps/imesh/MOAB_iMesh_unit_tests
+itaps/imesh/partest
+itaps/imesh/ScdMeshF77
+itaps/imesh/ScdMeshF90
+itaps/imesh/testc_cbind
+*.la
+*.la
+*.lai
+lib
+lib/*
+.libs
 libtool
+*.lo
+*.log
+makefile
+Makefile
+*/Makefile
+*/**/Makefile
+*/**/Makefile.in
+*/Makefile.in
+Makefile.in
+moab.config
+MOABConfig.cmake
+moab.creator*
+moab.files
+moab.includes
 moab.make
+*.o
+.project
+*.rej
+share/*
+share/doc/moab
+share/man/man1
+*.so
 src/FCDefs.h
+src/io/mhdf/h5minfo
+src/io/mhdf/h5mvalidate
 src/MBCN_protos.h
-src/MOAB_FCDefs.h
 src/moab/EntityHandle.hpp
-src/moab/Version.h
+src/MOAB_FCDefs.h
 src/moab/stamp-h2
 src/moab/stamp-h3
+src/moab/Version.h
 src/parallel/moab_mpi_config.h
 src/parallel/stamp-h4
 src/stamp-h5
 stamp-h1
-tools/mbcoupler/tests/
-tools/mbzoltan/Config.moab
-tools/vtkMOABReader/CMakeLists.txt
-tools/vtkMOABReaderNew/CMakeLists.txt
-.deps
-Makefile.in
-Makefile
-*/Makefile.in
-*/Makefile
-*/**/Makefile.in
-*/**/Makefile
-.libs
-*.o
-*.log
-*.lo
-*.la
-*.a
-*.so
-include/*
-lib/*
-share/*
-bin/*
-*~
-examples/HelloMoabPar
-examples/TestExodusII
-itaps/igeom/FBiGeom_protos.h
-itaps/igeom/testSmooth2
-itaps/igeom/testSmoothGeom
-itaps/igeom/testgeom
-itaps/imesh/FindAdjacencyF90
-itaps/imesh/MOAB_iMeshP_unit_tests
-itaps/imesh/ScdMeshF77
-itaps/imesh/ScdMeshF90
-itaps/imesh/partest
 test/adaptive_kd_tree_tests
 test/bsp_tree_poly_test
 test/bsp_tree_test
-test/*.gen
+test/CMakeLists.txt
 test/coords_connect_iterate
 test/cropvol_test
 test/dual/dual_test
+test/elem_eval_test
 test/file_options_test
+test/*.g
+test/*.g
+test/*.gen
+test/*.gen
 test/geom_util_test
 test/gttool_test
+test/gttool_test
 test/h5file/dump_sets
 test/h5file/h5legacy
 test/h5file/h5partial
@@ -102,13 +135,14 @@ test/h5file/h5regression
 test/h5file/h5sets_test
 test/h5file/h5test
 test/h5file/h5varlen
-test/*.g
 test/homxform_test
+test/io/*.ccmg
+test/io/ccmio_test
 test/io/cub_file_test
 test/io/exodus_test
+test/io/*.g
 test/io/gmsh_test
 test/io/ideas_test
-test/io/*.g
 test/io/nastran_test
 test/io/read_cgm_test
 test/io/read_nc
@@ -133,7 +167,6 @@ 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
@@ -142,6 +175,8 @@ test/parallel/par_intx_sph
 test/parallel/parallel_hdf5_test
 test/parallel/parallel_unit_tests
 test/parallel/parallel_write_test
+test/parallel/par_coupler_test
+test/parallel/par_intx_sph
 test/parallel/parmerge
 test/parallel/partcheck
 test/parallel/pcomm_serial
@@ -152,39 +187,68 @@ test/parallel/scdtest
 test/parallel/structured3
 test/parallel/uber_parallel_test
 test/parallel/ucdtrvpart
+test/parallel/*.vtk
 test/perf/adj_time
 test/perf/perf
 test/perf/perftool
+test/perf/point_in_elem
+test/perf/runtest
 test/perf/seqperf
 test/perf/tstt_perf_binding
+test/perf/point_location/elem_eval_time
+test/perf/point_location/point_location
 test/range_test
 test/reorder_test
 test/scdseq_test
 test/scd_test_partn
 test/seq_man_test
+test/spatial_locator_test
+test/test_boundbox
 test/tag_test
 test/test_adj
 test/test_prog_opt
+test/TestRunner.hpp
 test/var_len_test
 test/var_len_test_no_template
 test/xform_test
+tools/dagmc/dagmc_preproc
 tools/dagmc/pt_vol_test
+tools/dagmc/quads_to_tris
 tools/dagmc/ray_fire_test
 tools/dagmc/test_geom
 tools/dagmc/update_coords
+tools/hexmodops
+tools/mbconvert
 tools/mbcoupler/*.h5m
+tools/mbcoupler/*.g
+tools/mbcoupler/tests/
 tools/mbcslam/case1_test
 tools/mbcslam/intersect1.h5m
-tools/mbcslam/intx.vtk
 tools/mbcslam/intx1.vtk
 tools/mbcslam/intx_in_plane_test
 tools/mbcslam/intx_on_sphere_test
+tools/mbcslam/intx.vtk
 tools/mbcslam/lagr.h5m
-tools/mbcslam/spec_visu_test
 tools/mbcslam/spectral.vtk
+tools/mbcslam/spec_visu_test
 tools/mbcslam/spherical_area_test
-.project
-.cproject
-examples/*.h5m
-examples/ReduceExchangeTags
-
+tools/mbdepth
+tools/mbgsets
+tools/mbmem
+tools/mbsize
+tools/mbskin
+tools/mbsurfplot
+tools/mbtagprop
+tools/mbzoltan/Config.moab
+tools/spheredecomp
+tools/vtkMOABReader/CMakeLists.txt
+tools/vtkMOABReaderNew/CMakeLists.txt
+tools/vtkMOABReaderNew/CMakeCache.txt
+tools/vtkMOABReaderNew/CMakeFiles/*
+tools/vtkMOABReaderNew/cmake_install.cmake
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin.qrc
+tools/vtkMOABReaderNew/vtkMoabReaderPluginInit.cxx
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin_Plugin.cxx
+tools/vtkMOABReaderNew/vtkMoabReaderPlugin_Plugin.h
+tools/vtkMOABReaderNew/vtkSMvtkMoabReaderPluginInstantiator.cxx
+tools/vtkMOABReaderNew/vtkSMvtkMoabReaderPluginInstantiator.h

diff --git a/MeshFiles/unittest/16_unmerged_hex.h5m b/MeshFiles/unittest/16_unmerged_hex.h5m
new file mode 100644
index 0000000..2ebde86
Binary files /dev/null and b/MeshFiles/unittest/16_unmerged_hex.h5m differ

diff --git a/configure.ac b/configure.ac
index b08389a..cc1d3e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -623,7 +623,6 @@ AC_HELP_STRING([--disable-tools],[Disable all tools by default])],
                          [ENABLE_TOOLS=$enableval],[ENABLE_TOOLS=] )
   # Individual tools
 MB_OPTIONAL_TOOL([mbconvert],    [yes])
-MB_OPTIONAL_TOOL([pointsearch],  [no])
 MB_OPTIONAL_TOOL([hexmodops],    [yes])
 MB_OPTIONAL_TOOL([qvdual],       [no] )
 MB_OPTIONAL_TOOL([vtkMOABReader],[${VTKMOAB_DEFAULT}] )
@@ -1184,6 +1183,7 @@ AC_CONFIG_FILES([Makefile
                  src/Makefile
                  src/io/Makefile
                  src/io/mhdf/Makefile
+		 src/LocalDiscretization/Makefile
                  src/parallel/Makefile
                  src/oldinc/Makefile
                  test/Makefile
@@ -1191,6 +1191,7 @@ AC_CONFIG_FILES([Makefile
                  test/dual/Makefile
                  test/obb/Makefile
                  test/perf/Makefile
+                 test/perf/point_location/Makefile
                  test/io/Makefile
                  test/parallel/Makefile
                  test/oldinc/Makefile

diff --git a/doc/MOAB-UG.doc b/doc/MOAB-UG.doc
index 5cf591c..b7668b8 100644
Binary files a/doc/MOAB-UG.doc and b/doc/MOAB-UG.doc differ

diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
index a6a6f4a..8f4a6be 100644
--- a/doc/UG/moabUG.h
+++ b/doc/UG/moabUG.h
@@ -895,7 +895,7 @@ Note that using the iMesh interface from Fortran-based applications requires a c
 
   \section representation 8.Structured Mesh Representation
 
-A structured mesh is defined as a D-dimensional mesh whose interior vertices have 2D connected edges.   Structured mesh can be stored without connectivity, if certain information is kept about the parametric space of each structured block of mesh.  MOAB can represent structured mesh with implicit connectivity, saving approximately 57% of the storage cost compared to an unstructured representation<sup>7</sup>.  Since connectivity must be computed on the fly, these queries execute a bit slower than those for unstructured mesh.  More information on the theory behind MOAB's structured mesh representation can be found in 
+A structured mesh is defined as a D-dimensional mesh whose interior vertices have 2D connected edges.   Structured mesh can be stored without connectivity, if certain information is kept about the parametric space of each structured block of mesh.  MOAB can represent structured mesh with implicit connectivity, saving approximately 57% of the storage cost compared to an unstructured representation<sup>7</sup>.  Since connectivity must be computed on the fly, these queries execute a bit slower than those for unstructured mesh.  More information on the theory behind MOAB's structured mesh representation can be found in “MOAB-SD: Integrated structured and unstructured mesh representation”[17].
 
 Currently, MOAB's structured mesh representation can only be used by creating structured mesh at runtime; that is, structured mesh is saved/restored in an unstructured format in MOAB's HDF5-based native save format.  For more details on how to use MOAB's structured mesh representation, see the scdseq_test.cpp source file in the test/ directory.
 

diff --git a/examples/makefile b/examples/makefile
index 3b848d2..ff5876c 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -47,6 +47,9 @@ HelloParMOAB: HelloParMOAB.o
 TestExodusII: TestExodusII.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+point_in_elem_search: point_in_elem_search.o
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
+
 clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 

diff --git a/examples/old/Makefile.am b/examples/old/Makefile.am
index d0a33b9..21e6da3 100644
--- a/examples/old/Makefile.am
+++ b/examples/old/Makefile.am
@@ -7,7 +7,6 @@
 check_PROGRAMS = FileRead \
                  GeomSetHierarchy \
                  GetEntities \
-                 KDTree \
 		 ObbTree \
                  SetsNTags \
                  SkinMesh \
@@ -28,7 +27,6 @@ GetEntities_SOURCES = simple/GetEntities.cpp
 SetsNTags_SOURCES = SetsNTags.cpp
 SkinMesh_SOURCES = SkinMesh.cpp
 SurfArea_SOURCES = SurfArea.cpp
-KDTree_SOURCES = KDTree.cpp
 ObbTree_SOURCES = ObbTree.cpp
 
 exampledir = ${docdir}/examples
@@ -38,7 +36,6 @@ nobase_example_DATA = \
                GeomSetHierarchy.cpp \
                simple/GetEntities.cpp \
                simple/makefile \
-               KDTree.cpp \
 	       ObbTree.cpp \
                SetsNTags.cpp \
                SkinMesh.cpp \

diff --git a/examples/point_in_elem_search.cpp b/examples/point_in_elem_search.cpp
new file mode 100644
index 0000000..a917fa0
--- /dev/null
+++ b/examples/point_in_elem_search.cpp
@@ -0,0 +1,86 @@
+/** \brief This test shows how to perform local point-in-element searches with MOAB's new tree searching functionality.  
+ *
+ * MOAB's SpatialLocator functionality performs point-in-element searches over a local or parallel mesh.
+ * SpatialLocator is flexible as to what kind of tree is used and what kind of element basis functions are 
+ * used to localize elements and interpolate local fields.
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include "moab/Range.hpp"
+#include "moab/AdaptiveKDTree.hpp"
+#include "moab/ElemEvaluator.hpp"
+#include "moab/LinearHex.hpp"
+#include "moab/CN.hpp"
+#include "moab/SpatialLocator.hpp"
+
+using namespace moab;
+
+#define ERR(s) if (MB_SUCCESS != rval) \
+    {std::string str;mb.get_last_error(str); std::cerr << s << str << std::endl; return 1;}
+
+int main(int argc, char **argv) {
+
+  int num_queries = 1000000;
+  
+  if (argc == 1) {
+    std::cout << "Usage: " << argv[0] << "<filename> [num_queries]" << std::endl;
+    return 0;
+  }
+  else if (argc == 3) num_queries = atoi(argv[2]);
+
+    // instantiate & load a file
+  moab::Core mb;
+
+    // load the file
+  ErrorCode rval = mb.load_file(argv[argc-1]); ERR("Error loading file");
+  
+    // get all 3d elements in the file
+  Range elems;
+  rval = mb.get_entities_by_dimension(0, 3, elems); ERR("Error getting 3d elements");
+  
+    // create a tree to use for the location service
+  AdaptiveKDTree tree(&mb);
+
+    // specify an evaluator based on linear hexes
+  ElemEvaluator el_eval(&mb);
+
+    // build the SpatialLocator
+  SpatialLocator sl(&mb, elems, &tree);
+  
+    // get the box extents
+  BoundBox box;
+  CartVect box_extents, pos;
+  rval = sl.get_bounding_box(box); ERR("Problem getting tree bounding box");
+  box_extents = box.bMax - box.bMin;
+  
+    // query at random places in the tree
+  CartVect params;
+  bool is_inside;
+  int num_inside = 0;
+  EntityHandle elem;
+  for (int i = 0; i < num_queries; i++) {
+    pos = box.bMin + 
+        CartVect(box_extents[0]*.01*(rand()%100), box_extents[1]*.01*(rand()%100), box_extents[2]*.01*(rand()%100));
+    ErrorCode tmp_rval = sl.locate_point(pos.array(), elem, params.array(), 0.0, 0.0, &is_inside);
+    if (MB_SUCCESS != tmp_rval) rval = tmp_rval;
+    if (is_inside) num_inside++;
+  }
+  
+  std::cout << "Mesh contains " << elems.size() << " elements of type " 
+            << CN::EntityTypeName(mb.type_from_handle(*elems.begin())) << std::endl;
+  std::cout << "Bounding box min-max = (" << box.bMin[0] << "," << box.bMin[1] << "," << box.bMin[2] << ")-("
+            << box.bMax[0] << "," << box.bMax[1] << "," << box.bMax[2] << ")" << std::endl;
+  std::cout << "Queries inside box = " << num_inside << "/" << num_queries << " = " 
+            << 100.0*((double)num_inside)/num_queries << "%" << std::endl;
+}
+
+    
+  
+  
+  
+

diff --git a/itaps/igeom/FBiGeom_MOAB.cpp b/itaps/igeom/FBiGeom_MOAB.cpp
index cb889bd..7fcd2b1 100644
--- a/itaps/igeom/FBiGeom_MOAB.cpp
+++ b/itaps/igeom/FBiGeom_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/GeomTopoTool.hpp"
 #include "moab/OrientedBoxTreeTool.hpp"
 #include "moab/CartVect.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "MBTagConventions.hpp"
 #include <stdlib.h>
 #include <cstring>

diff --git a/itaps/imesh/iMeshP_MOAB.cpp b/itaps/imesh/iMeshP_MOAB.cpp
index e554fba..51254ca 100644
--- a/itaps/imesh/iMeshP_MOAB.cpp
+++ b/itaps/imesh/iMeshP_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/Range.hpp"
 #include "moab/CN.hpp"
 #include "moab/MeshTopoUtil.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "moab/ParallelComm.hpp"
 #include "MBParallelConventions.h"
 #include "MBIter.hpp"

diff --git a/itaps/imesh/iMesh_MOAB.cpp b/itaps/imesh/iMesh_MOAB.cpp
index d09fec1..68c0b72 100644
--- a/itaps/imesh/iMesh_MOAB.cpp
+++ b/itaps/imesh/iMesh_MOAB.cpp
@@ -4,7 +4,7 @@
 #include "moab/CN.hpp"
 #include "moab/MeshTopoUtil.hpp"
 #include "moab/ScdInterface.hpp"
-#include "FileOptions.hpp"
+#include "moab/FileOptions.hpp"
 #include "iMesh_MOAB.hpp"
 #include "MBIter.hpp"
 #include "MBTagConventions.hpp"
@@ -3303,7 +3303,7 @@ void iMesh_createStructuredMesh(iMesh_Instance instance,
   ScdBox *scd_box;
   rval = scdi->construct_box(HomCoord(local_dims[0], local_dims[1], (-1 != local_dims[2] ? local_dims[2] : 0), 1),
                              HomCoord(local_dims[3], local_dims[4], (-1 != local_dims[5] ? local_dims[5] : 0), 1),
-                             NULL, 0, scd_box);
+                             NULL, 0, scd_box, NULL, NULL, (vert_gids ? true : false));
   CHKERR(rval, "Trouble creating scd vertex sequence.");
 
     // set the global box parameters

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/a204e09daeeb/
Changeset:   a204e09daeeb
Branch:      None
User:        danwu
Date:        2013-09-23 18:19:28
Summary:     Merged fathomteam/moab into master
Affected #:  12 files

diff --git a/MeshFiles/unittest/Makefile.am b/MeshFiles/unittest/Makefile.am
index 16dc2ed..a1784ee 100644
--- a/MeshFiles/unittest/Makefile.am
+++ b/MeshFiles/unittest/Makefile.am
@@ -1,6 +1,7 @@
 SUBDIRS = io
 
 EXTRA_DIST  = 125hex.g \
+              16_unmerged_hex.h5m \
               1hex.g \
               1khex.g \
               1tet.g \

diff --git a/examples/HelloMOAB.cpp b/examples/HelloMOAB.cpp
index 6129233..6ca2b23 100644
--- a/examples/HelloMOAB.cpp
+++ b/examples/HelloMOAB.cpp
@@ -57,6 +57,8 @@ int main( int argc, char** argv )
   cout << "Number of edges is " << edges.size() <<  endl;
   cout << "Number of faces is " << faces.size() <<  endl;
   cout << "Number of elements is " << elems.size() <<  endl;
-  
+
+  delete iface;
+
   return 0;
 }

diff --git a/src/MergeMesh.cpp b/src/MergeMesh.cpp
index 4cc8158..7293e17 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(0, elems, 0, skin_range);
+  moab::ErrorCode result = skinner.find_skin(0, elems, 0, skin_range, false, false);
   if (moab::MB_SUCCESS != result) return result;
 
   // create a tag to mark merged-to entity; reuse tree_root
@@ -232,16 +232,16 @@ moab::ErrorCode MergeMesh::merge_higher_dimensions(moab::Range &elems)
   for(int dim = 1; dim <3; dim++){
     skinEnts.clear();
     moreDeadEnts.clear();
-    result = skinner.find_skin(0, elems, dim, skinEnts);
+    result = skinner.find_skin(0, elems, dim, skinEnts, false, false);
     //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();
       //Get the adjacencies 1 dimension lower
-      result = mbImpl->get_adjacencies(&(*skinIt), 1, dim-1, true, adj);
+      result = mbImpl->get_adjacencies(&(*skinIt), 1, dim-1, false, adj);
       if(result != moab::MB_SUCCESS) return result;
       //See what other entities share these adjacencies
       matches.clear();
-      result = mbImpl->get_adjacencies(adj, dim, true, matches, moab::Interface::INTERSECT);
+      result = mbImpl->get_adjacencies(adj, dim, false, matches, moab::Interface::INTERSECT);
       if(result != moab::MB_SUCCESS) return result;
       //If there is more than one entity, then we have some to merge and erase
       if(matches.size() > 1){

diff --git a/src/Skinner.cpp b/src/Skinner.cpp
index b5fd24e..c3c6b1b 100644
--- a/src/Skinner.cpp
+++ b/src/Skinner.cpp
@@ -1015,11 +1015,12 @@ ErrorCode Skinner::find_skin(const EntityHandle this_set,
                              const Range &entities,
                                  int dim,
                                  Range &skin_entities,
-                                 bool create_vert_elem_adjs) 
+                                 bool create_vert_elem_adjs,
+                                 bool create_skin_elements)
 {
   Range tmp_skin;
   ErrorCode result = find_skin(this_set, entities, (dim==0), tmp_skin, 0,
-                                 create_vert_elem_adjs, true);
+                                 create_vert_elem_adjs, create_skin_elements);
   if (MB_SUCCESS != result || tmp_skin.empty()) return result;
   
   if (tmp_skin.all_of_dimension(dim)) {
@@ -1029,7 +1030,7 @@ ErrorCode Skinner::find_skin(const EntityHandle this_set,
       skin_entities.merge(tmp_skin);
   }
   else {
-    result = thisMB->get_adjacencies( tmp_skin, dim, true, skin_entities, 
+    result = thisMB->get_adjacencies( tmp_skin, dim, create_skin_elements, skin_entities,
                                       Interface::UNION );
   }
   

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 4f2ac51..f750e78 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -232,7 +232,7 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
       conn_fname = "HommeMapping.nc";
   }
 
-  int success;
+  int success = 0;
 
   int rank = 0;
   int procs = 1;
@@ -265,9 +265,11 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
   ERRORR(rval, "Failed to get dimensions for connectivity.");
 
   // Read connectivity into temporary variable
-  int num_fine_quads, num_coarse_quads, start_idx;
+  int num_fine_quads = 0;
+  int num_coarse_quads = 0;
+  int start_idx = 0;
   std::vector<std::string>::iterator vit;
-  int idx;
+  int idx = 0;
   if ((vit = std::find(conn_names.begin(), conn_names.end(), "ncells")) != conn_names.end())
     idx = vit - conn_names.begin();
   else if ((vit = std::find(conn_names.begin(), conn_names.end(), "ncenters")) != conn_names.end())

diff --git a/src/moab/Skinner.hpp b/src/moab/Skinner.hpp
index 7ec5450..4eb2f51 100644
--- a/src/moab/Skinner.hpp
+++ b/src/moab/Skinner.hpp
@@ -119,7 +119,8 @@ public:
                       const Range &entities,
                       int dim,
                       Range &skin_entities,
-                      bool create_vert_elem_adjs = false);
+                      bool create_vert_elem_adjs = false,
+                      bool create_skin_elements = true);
 
   ErrorCode classify_2d_boundary( const Range &boundary,
                                      const Range &bar_elements,

diff --git a/test/Makefile.am b/test/Makefile.am
index 467b2a2..99c5211 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -48,13 +48,13 @@ TESTS = range_test \
 	coords_connect_iterate \
 	elem_eval_test \
 	spatial_locator_test \
-        mergemesh_test \
 	test_boundbox
 
 if HDF5_FILE
   TESTS += mbfacet_test \
         gttool_test \
         cropvol_test \
+        mergemesh_test \
         mbground_test
 endif
 
@@ -76,6 +76,7 @@ MOSTLYCLEANFILES = mb_write.g \
                    tri_mid_edge_face_nodes.g \
                    mb_stress_out.g \
                    merge_test.g \
+                   mm_out.h5m \
                    tree.h5m 
 
 # Tests and such

diff --git a/test/mergemesh_test.cpp b/test/mergemesh_test.cpp
index 0b382e6..fca5304 100644
--- a/test/mergemesh_test.cpp
+++ b/test/mergemesh_test.cpp
@@ -38,11 +38,11 @@ int main( int argc, char* argv[] )
     }
 
     // Fixed for now
-//    const char *outfile = "mm_out.h5m";
-//    rval = iface->write_mesh( outfile);
-//    if (MB_SUCCESS != rval) {
-//        std::cerr << "Error saving file: " << outfile << std::endl;
-//        exit(2);
-//    }
+    const char *outfile = "mm_out.h5m";
+    rval = iface->write_mesh( outfile);
+    if (MB_SUCCESS != rval) {
+        std::cerr << "Error saving file: " << outfile << std::endl;
+        exit(2);
+    }
     return 0;
 }

diff --git a/tools/mbcoupler/Coupler.cpp b/tools/mbcoupler/Coupler.cpp
index 71231b8..f7f74b2 100644
--- a/tools/mbcoupler/Coupler.cpp
+++ b/tools/mbcoupler/Coupler.cpp
@@ -6,6 +6,7 @@
 #include "iMesh_extensions.h"
 #include "moab/gs.hpp"
 #include "moab/TupleList.hpp"
+#include "moab/Error.hpp"
 #include "iostream"
 #include <stdio.h>
 #include <algorithm>
@@ -518,6 +519,27 @@ ErrorCode Coupler::test_local_box(double *xyz,
   return MB_SUCCESS;
 }
 
+ErrorCode Coupler::interpolate(Coupler::Method method,
+                                      const std::string &interp_tag,
+                                      double *interp_vals,
+                                      TupleList *tl,
+                                      bool normalize)
+{
+  Tag tag;
+  ErrorCode result ;
+  if (_spectralSource)
+    result = mbImpl->tag_get_handle(interp_tag.c_str(), _ntot, MB_TYPE_DOUBLE, tag);
+  else
+    result = mbImpl->tag_get_handle(interp_tag.c_str(), 1, MB_TYPE_DOUBLE, tag);
+  if (MB_SUCCESS != result) {
+    std::ostringstream str;
+    str << "Failed to get handle for interpolation tag \"" << interp_tag << "\"";
+    mError->set_last_error(str.str());
+    return result;
+  }
+  return interpolate(method, tag, interp_vals, tl, normalize);
+}
+
 ErrorCode Coupler::interpolate(Coupler::Method *methods,
                                Tag *tags,
                                int *points_per_method,

diff --git a/tools/mbcoupler/Coupler.hpp b/tools/mbcoupler/Coupler.hpp
index 74170d5..705e2dc 100644
--- a/tools/mbcoupler/Coupler.hpp
+++ b/tools/mbcoupler/Coupler.hpp
@@ -29,7 +29,6 @@
 #include "moab/Interface.hpp"
 #include "moab/CartVect.hpp"
 #include "moab/TupleList.hpp"
-#include "moab/Error.hpp"
 
 #include <sstream>
 
@@ -41,6 +40,8 @@ class AdaptiveKDTree;
   
 class TupleList;
 
+class Error;
+
 class Coupler
 {
 public:
@@ -530,27 +531,6 @@ private:
     // error object used to set last error on interface
   Error *mError;
 };
-
-inline ErrorCode Coupler::interpolate(Coupler::Method method,
-                                      const std::string &interp_tag,
-                                      double *interp_vals,
-                                      TupleList *tl,
-                                      bool normalize)
-{
-  Tag tag;
-  ErrorCode result ;
-  if (_spectralSource)
-    result = mbImpl->tag_get_handle(interp_tag.c_str(), _ntot, MB_TYPE_DOUBLE, tag);
-  else
-    result = mbImpl->tag_get_handle(interp_tag.c_str(), 1, MB_TYPE_DOUBLE, tag);
-  if (MB_SUCCESS != result) {
-    std::ostringstream str;
-    str << "Failed to get handle for interpolation tag \"" << interp_tag << "\"";
-    mError->set_last_error(str.str());
-    return result;
-  }
-  return interpolate(method, tag, interp_vals, tl, normalize);
-}
   
 inline ErrorCode Coupler::interpolate(Coupler::Method method,
                                       Tag tag,

diff --git a/tools/mbcoupler/ElemUtil.hpp b/tools/mbcoupler/ElemUtil.hpp
index 1db4c9e..219323b 100644
--- a/tools/mbcoupler/ElemUtil.hpp
+++ b/tools/mbcoupler/ElemUtil.hpp
@@ -168,7 +168,7 @@ namespace ElemUtil {
     /**\brief Shape function space for a linear tetrahedron, obtained by a pushforward of the canonical affine shape functions. */
     class LinearTet : public Map {
     public:
-      LinearTet(const std::vector<CartVect>& vertices) : Map(vertices){};
+      LinearTet(const std::vector<CartVect>& vertices) : Map(vertices){ LinearTet::set_vertices(vertex);};
       LinearTet();
       virtual ~LinearTet();
       /* Override the evaluation routines to take advantage of the properties of P1. */

diff --git a/tools/mbcslam/Intx2MeshOnSphere.cpp b/tools/mbcslam/Intx2MeshOnSphere.cpp
index a875d7b..0952ef6 100644
--- a/tools/mbcslam/Intx2MeshOnSphere.cpp
+++ b/tools/mbcslam/Intx2MeshOnSphere.cpp
@@ -439,10 +439,10 @@ ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagE
     int blueIndex, redIndex;
     rval =  mb->tag_get_data(blueParentTag, &poly, 1, &blueIndex);
     ERRORR(rval, "can't get blue tag");
-    EntityHandle blue = rs1[blueIndex];
+    //EntityHandle blue = rs1[blueIndex];
     rval =  mb->tag_get_data(redParentTag, &poly, 1, &redIndex);
     ERRORR(rval, "can't get red tag");
-    EntityHandle red=rs2[redIndex];
+    //EntityHandle red = rs2[redIndex];
     // big assumption here, red and blue are "parallel" ;we should have an index from
     // blue to red (so a deformed blue corresponds to an arrival red)
     double areap = area_spherical_element(mb, poly, R);


https://bitbucket.org/fathomteam/moab/commits/ca9fc9066e95/
Changeset:   ca9fc9066e95
Branch:      None
User:        danwu
Date:        2013-09-25 21:16:19
Summary:     Merged fathomteam/moab into master
Affected #:  19 files

diff --git a/examples/GetEntities.cpp b/examples/GetEntities.cpp
index 6c6a956..5124529 100644
--- a/examples/GetEntities.cpp
+++ b/examples/GetEntities.cpp
@@ -29,19 +29,28 @@ int main(int argc, char **argv) {
     // instantiate & load a mesh from a file
   Core *mb = new Core();
   ErrorCode rval = mb->load_mesh(test_file_name.c_str());
-  if (MB_SUCCESS != rval) return 1;
+  if (MB_SUCCESS != rval) {
+    delete mb;
+    return 1;
+  }
 
   Range ents;
 
     // get all entities in the database
   rval = mb->get_entities_by_handle(0, ents);
-  if (MB_SUCCESS != rval) return 1;
+  if (MB_SUCCESS != rval) {
+    delete mb;
+    return 1;
+  }
 
   for (Range::iterator it = ents.begin(); it != ents.end(); it++) {
     if (MBVERTEX == mb->type_from_handle(*it)) {
       Range adjs;
       rval = mb->get_adjacencies(&(*it), 1, 3, false, adjs);
-      if (MB_SUCCESS != rval) return 1;
+      if (MB_SUCCESS != rval) {
+        delete mb;
+        return 1;
+      }
       cout << "Vertex " << mb->id_from_handle(*it) << " adjacencies:" << endl;
       adjs.print();
     }
@@ -49,12 +58,18 @@ int main(int argc, char **argv) {
       const EntityHandle *connect;
       int num_connect;
       rval = mb->get_connectivity(*it, connect, num_connect);
-      if (MB_SUCCESS != rval) return 1;
+      if (MB_SUCCESS != rval) {
+        delete mb;
+        return 1;
+      }
       cout << CN::EntityTypeName(mb->type_from_handle(*it)) << " " << mb->id_from_handle(*it) << " vertex connectivity is: ";
-      for (int i = 0; i < num_connect; i++) cout << mb->id_from_handle(connect[i]) << " ";
+      for (int i = 0; i < num_connect; i++)
+        cout << mb->id_from_handle(connect[i]) << " ";
       cout << endl;
     }
   }
-  
+
+  delete mb;
+
   return 0;
 }

diff --git a/examples/HelloParMOAB.cpp b/examples/HelloParMOAB.cpp
index 75daeda..5bcc4ab 100644
--- a/examples/HelloParMOAB.cpp
+++ b/examples/HelloParMOAB.cpp
@@ -20,20 +20,23 @@ int main(int argc, char **argv)
 
   string options;
 
-    // need option handling here for input filename
+  // Need option handling here for input filename
   if (argc > 1){
-    //user has input a mesh file
+    // user has input a mesh file
     test_file_name = argv[1];
   }  
 
   options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS";
 
-  // get MOAB instance and read the file with the specified options
-  Interface *mb = new Core;
-  if (NULL == mb) return 1;
-  // get the ParallelComm instance
+  // Get MOAB instance and read the file with the specified options
+  Interface* mb = new Core;
+  if (NULL == mb)
+    return 1;
+
+  // Get the ParallelComm instance
   ParallelComm* pcomm = new ParallelComm(mb, MPI_COMM_WORLD);
-  int nprocs = pcomm->proc_config().proc_size(), rank = pcomm->proc_config().proc_rank();
+  int nprocs = pcomm->proc_config().proc_size();
+  int rank = pcomm->proc_config().proc_rank();
   MPI_Comm comm = pcomm->proc_config().proc_comm();
 
   if (rank == 0)
@@ -41,62 +44,81 @@ int main(int argc, char **argv)
          << " on " << nprocs << " processors\n";
 
   ErrorCode rval = mb->load_file(test_file_name.c_str(), 0, options.c_str());
-  if (rval != MB_SUCCESS) return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
 
   Range shared_ents;
-    // get entities shared with all other processors
+  // Get entities shared with all other processors
   rval = pcomm->get_shared_entities(-1, shared_ents);
-  if (rval != MB_SUCCESS) return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
 
-    // filter shared entities with not not_owned, which means owned
+  // Filter shared entities with not not_owned, which means owned
   Range owned_entities;
   rval = pcomm->filter_pstatus(shared_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_entities);
-  if (rval != MB_SUCCESS) return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
 
-  unsigned int nums[4]={0}; // to store the owned entities per dimension
-  for (int i=0; i<4; i++) nums[i]=(int)owned_entities.num_of_dimension(i);
+  unsigned int nums[4] = {0}; // to store the owned entities per dimension
+  for (int i = 0; i < 4; i++)
+    nums[i] = (int)owned_entities.num_of_dimension(i);
   vector<int> rbuf(nprocs*4, 0);
-  MPI_Gather( nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, MPI_COMM_WORLD);
-  // print the stats gathered:
+  MPI_Gather(nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, MPI_COMM_WORLD);
+  // Print the stats gathered:
   if (rank == 0) {
-    for (int i=0; i<nprocs; i++)
+    for (int i = 0; i < nprocs; i++)
       cout << " Shared, owned entities on proc " << i << ": " << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces, " << rbuf[4*i+3] << " elements" << endl;
+          rbuf[4*i + 1] << " edges, " << rbuf[4*i + 2] << " faces, " << rbuf[4*i + 3] << " elements" << endl;
   }
 
-    // Now exchange 1 layer of ghost elements, using vertices as bridge
-    // (we could have done this as part of reading process, using the PARALLEL_GHOSTS read option)
+  // Now exchange 1 layer of ghost elements, using vertices as bridge
+  // (we could have done this as part of reading process, using the PARALLEL_GHOSTS read option)
   rval = pcomm->exchange_ghost_cells(3, // int ghost_dim,
                                      0, // int bridge_dim,
                                      1, //int num_layers,
                                      0, //int addl_ents,
                                      true); // bool store_remote_handles);
-  if (rval != MB_SUCCESS) return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
 
-  // repeat the reports, after ghost exchange
+  // Repeat the reports, after ghost exchange
   shared_ents.clear();
   owned_entities.clear();
   rval = pcomm->get_shared_entities(-1, shared_ents);
-  if (rval != MB_SUCCESS) return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
   rval = pcomm->filter_pstatus(shared_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_entities);
-  if (rval != MB_SUCCESS)  return 1;
+  if (rval != MB_SUCCESS) {
+    delete mb;
+    return 1;
+  }
 
   // find out how many shared entities of each dimension are owned on this processor
-  for (int i=0; i<4; i++)
-    nums[i]=(int)owned_entities.num_of_dimension(i);
+  for (int i = 0; i < 4; i++)
+    nums[i] = (int)owned_entities.num_of_dimension(i);
 
   // gather the statistics on processor 0
-  MPI_Gather( nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, comm);
-  if (rank == 0)
-  {
+  MPI_Gather(nums, 4, MPI_INT, &rbuf[0], 4, MPI_INT, 0, comm);
+  if (rank == 0) {
     cout << " \n\n After exchanging one ghost layer: \n";
-    for (int i=0; i<nprocs; i++)
-    {
+    for (int i = 0; i < nprocs; i++) {
       cout << " Shared, owned entities on proc " << i << ": " << rbuf[4*i] << " verts, " <<
-          rbuf[4*i+1] << " edges, " << rbuf[4*i+2] << " faces, " << rbuf[4*i+3] << " elements" << endl;
+          rbuf[4*i + 1] << " edges, " << rbuf[4*i + 2] << " faces, " << rbuf[4*i + 3] << " elements" << endl;
     }
   }
 
+  delete mb;
+
   MPI_Finalize();
 
   return 0;

diff --git a/examples/old/FileRead.cpp b/examples/old/FileRead.cpp
index bff9e28..b1abda0 100644
--- a/examples/old/FileRead.cpp
+++ b/examples/old/FileRead.cpp
@@ -160,5 +160,8 @@ int main(int argc, char **argv) {
      cout << "Writing output file " << outfile << endl;
      mb->write_file(outfile); 
    }
+
+   delete mb;
+
    return 0;
 }  

diff --git a/examples/old/GeomSetHierarchy.cpp b/examples/old/GeomSetHierarchy.cpp
index a49dafe..493baa7 100644
--- a/examples/old/GeomSetHierarchy.cpp
+++ b/examples/old/GeomSetHierarchy.cpp
@@ -79,5 +79,9 @@ int main(int argc, char **argv) {
         }
       }
     }
-  } 
+  }
+
+  delete mb;
+
+  return 0;
 }

diff --git a/examples/old/ObbTree.cpp b/examples/old/ObbTree.cpp
index 220681f..ff4aadf 100644
--- a/examples/old/ObbTree.cpp
+++ b/examples/old/ObbTree.cpp
@@ -22,9 +22,10 @@ int main(int argc, char **argv) {
   moab::Range tris;
   //moab::OrientedBoxTreeTool::Settings settings;
 
-  rval = mb->get_entities_by_type( 0, moab::MBTRI, tris );
+  rval = mb->get_entities_by_type(0, moab::MBTRI, tris);
   if (rval != moab::MB_SUCCESS) {
     std::cerr << "Couldn't get triangles." << std::endl;
+    delete mb;
     return 1;
   }
 
@@ -33,7 +34,8 @@ int main(int argc, char **argv) {
   //rval = tool.build(tris, tree_root, &settings);
   rval = tool.build(tris, tree_root);
   if (rval != moab::MB_SUCCESS) {
-    std::cerr << "Could'nt build tree." << std::endl;    
+    std::cerr << "Could'nt build tree." << std::endl;
+    delete mb;
     return 1;
   }
   
@@ -42,6 +44,7 @@ int main(int argc, char **argv) {
   rval = tool.box(tree_root, box_center, box_axis1, box_axis2, box_axis3);
   if (rval != moab::MB_SUCCESS) {
     std::cerr << "Couldn't get box for tree root set.";
+    delete mb;
     return 1;
   }
 
@@ -52,17 +55,19 @@ int main(int argc, char **argv) {
   std::vector<double> intersections;
   std::vector<moab::EntityHandle> intersection_facets;
 
-  for (int i=0; i<3; i++)
-    pnt_start[i] = box_center[i]-box_axis1[i];
+  for (int i = 0; i < 3; i++)
+    pnt_start[i] = box_center[i] - box_axis1[i];
 
-  if (ray_length>0) // normalize ray direction
-    for (int j=0; j<3; j++)
-      box_axis1[j]=2*box_axis1[j]/ray_length;
+  if (ray_length > 0) { // normalize ray direction
+    for (int j = 0; j < 3; j++)
+      box_axis1[j] = 2 * box_axis1[j] / ray_length;
+  }
   rval = tool.ray_intersect_triangles(intersections, intersection_facets, 
 				      tree_root, 10e-12, pnt_start, box_axis1,
 				      &ray_length);
   if (rval != moab::MB_SUCCESS) {
     std::cerr << "Couldn't ray tracing.";
+    delete mb;
     return 1;
   }
   
@@ -71,10 +76,11 @@ int main(int argc, char **argv) {
   std::cout << " ray direction: " << box_axis1[0] << " " << box_axis1[1] << " " << box_axis1[2] << "\n";
   std::cout << "# of intersections : " << intersections.size() << std::endl;
   std::cout << "intersection distances are on";
-  for (unsigned int i = 0; i < intersections.size(); i++) {
+  for (unsigned int i = 0; i < intersections.size(); i++)
     std::cout << " " << intersections[i];
-  }
   std::cout << " of ray length " << ray_length << std::endl;
 
+  delete mb;
+
   return 0;
 }

diff --git a/examples/old/simple/GetEntities.cpp b/examples/old/simple/GetEntities.cpp
index 1ac5783..31d24d7 100644
--- a/examples/old/simple/GetEntities.cpp
+++ b/examples/old/simple/GetEntities.cpp
@@ -8,18 +8,24 @@ int main(int argc, char **argv) {
     return 0;
   }
 
-    // instantiate & load a mesh from a file
+  // Instantiate & load a mesh from a file
   moab::Core *mb = new moab::Core();
   moab::ErrorCode rval = mb->load_mesh(argv[1]);
-  if (moab::MB_SUCCESS != rval) return 1;
+  if (moab::MB_SUCCESS != rval) {
+    delete mb;
+    return 1;
+  }
 
   moab::Range ents;
 
-    // iterate over dimensions
+  // Iterate over dimensions
   for (int d = 0; d <= 3; d++) {
     ents.clear();
     rval = mb->get_entities_by_dimension(0, d, ents);
-    if (moab::MB_SUCCESS != rval) return 1;
+    if (moab::MB_SUCCESS != rval) {
+      delete mb;
+      return 1;
+    }
     std::cout << "Found " << ents.size() << " " << d << "-dimensional entities:" << std::endl;
     for (moab::Range::iterator it = ents.begin(); it != ents.end(); it++) {
       moab::EntityHandle ent = *it;
@@ -27,5 +33,8 @@ int main(int argc, char **argv) {
                 << mb->id_from_handle(ent) << "." << std::endl;
     }
   }
+
+  delete mb;
+
   return 0;
 }

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/2d2dc236558d/
Changeset:   2d2dc236558d
Branch:      None
User:        danwu
Date:        2013-10-02 21:16:17
Summary:     Merged fathomteam/moab into master
Affected #:  2 files

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/parallel/ParallelComm.cpp b/src/parallel/ParallelComm.cpp
index d9e06d5..e83653b 100644
--- a/src/parallel/ParallelComm.cpp
+++ b/src/parallel/ParallelComm.cpp
@@ -2565,10 +2565,13 @@ ErrorCode ParallelComm::recv_entities(std::set<unsigned int>& recv_procs,
     if ((new_numps > 2 && !(new_pstat&(PSTATUS_INTERFACE|PSTATUS_GHOST|PSTATUS_NOT_OWNED))) ||
         (new_pstat&PSTATUS_INTERFACE && !(new_pstat&PSTATUS_NOT_OWNED))
         ) {
+      idx = std::min_element(&new_ps[0], &new_ps[0] + new_numps) - &new_ps[0];
       std::swap(new_ps[0], new_ps[idx]);
       std::swap(new_hs[0], new_hs[idx]);
+      if (new_ps[0] != (int)rank())
+        new_pstat |= PSTATUS_NOT_OWNED;
     }
-      
+
 /*    
     plist("new_ps", new_ps, new_numps);
     plist("new_hs", new_hs, new_numps);
@@ -5926,9 +5929,12 @@ ErrorCode ParallelComm::resolve_shared_ents(EntityHandle this_set,
                                            int old_nump, int new_nump,
                                            int *ps, EntityHandle *hs) 
   {
-    // set sharing data to what's passed in; may have to clean up existing sharing tags
-    // if things changed too much
-    
+    // If new nump is less than 3, the entity is no longer mutishared
+     if (old_nump > 2 && (pstatus & PSTATUS_MULTISHARED) && new_nump < 3) {
+       // Unset multishared flag
+       pstatus ^= PSTATUS_MULTISHARED;
+     }
+
     // check for consistency in input data
     assert(new_nump > 1 &&
            ((new_nump == 2 && pstatus&PSTATUS_SHARED && !(pstatus&PSTATUS_MULTISHARED)) || // if <= 2 must not be multishared
@@ -7778,9 +7784,10 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
   Tag ParallelComm::partition_tag()
   {  
     if (!partitionTag) {
+      int dum_id = -1;
       ErrorCode result = mbImpl->tag_get_handle(PARALLEL_PARTITION_TAG_NAME, 
                                                 1, MB_TYPE_INTEGER, partitionTag,
-                                                MB_TAG_SPARSE|MB_TAG_CREAT);
+                                                MB_TAG_SPARSE|MB_TAG_CREAT, &dum_id);
       if (MB_SUCCESS != result)
         return 0;
     }


https://bitbucket.org/fathomteam/moab/commits/926f0a92be84/
Changeset:   926f0a92be84
Branch:      None
User:        danwu
Date:        2013-10-08 16:05:42
Summary:     Merged fathomteam/moab into master
Affected #:  12 files

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/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index c0605e8..42eeca0 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -18,7 +18,7 @@ const int 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(MAX_EDGES_PER_CELL)
 , numCellGroups(0)
 {
 }
@@ -47,9 +47,9 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
   // Get max edges per cell
   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 > MAX_EDGES_PER_CELL) {
+      ERRORR(MB_FAILURE, "maxEdgesPerCell read from MPAS file has exceeded the limit");
     }
   }
 
@@ -182,6 +182,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 +251,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;
@@ -268,6 +271,7 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
   const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
   int& gatherSetRank = _readNC->gatherSetRank;
+  bool& noMixedElements = _readNC->noMixedElements;
 
   int rank = 0;
   int procs = 1;
@@ -312,8 +316,8 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   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);
+  NCDF_SIZE tmp_counts_2[2] = {static_cast<NCDF_SIZE>(nLocalCells), maxEdgesPerCell};
+  std::vector<int> vertices_on_local_cells(nLocalCells * maxEdgesPerCell);
   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.");
 
@@ -322,78 +326,33 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   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);
+  NCDF_SIZE tmp_counts_3[2] = {static_cast<NCDF_SIZE>(nLocalCells), maxEdgesPerCell};
+  std::vector<int> edges_on_local_cells(nLocalCells * maxEdgesPerCell);
   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.");
 
-  // 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);
-  }
-
-  // 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;
+  // Collect localGid for vertices and edges
   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]);
-        }
-      }
+  for (int i = 0; i < nLocalCells; i++) {
+    int num_edges = num_edges_on_local_cells[i];
+    for (int j = 0; j < num_edges; j++) {
+      local_verts_set.insert(vertices_on_local_cells[i * maxEdgesPerCell + j]);
+      local_edges_set.insert(edges_on_local_cells[i * maxEdgesPerCell + j]);
     }
   }
-
-  // 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.");
-
-  // Collect localGid for vertices
   std::copy(local_verts_set.rbegin(), local_verts_set.rend(), range_inserter(localGidVerts));
   nLocalVertices = localGidVerts.size();
+  std::copy(local_edges_set.rbegin(), local_edges_set.rend(), range_inserter(localGidEdges));
+  nLocalEdges = localGidEdges.size();
 
   // 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));
+  Range tmp_range;
+  ErrorCode 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);
 
@@ -412,17 +371,19 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
 
   // Get ptr to gid memory for local vertices
   Range local_verts_range(start_vertex, start_vertex + nLocalVertices - 1);
+  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 get tag iterator on global id tag.");
-  assert(count == (int) nLocalVertices);
-  gid_data = (int*) data;
+  ERRORR(rval, "Failed to get global id tag iterator on local vertices.");
+  assert(count == nLocalVertices);
+  int* 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);
+    ERRORR(rval, "Failed to get file id tag iterator on local vertices.");
+    assert(count == nLocalVertices);
     gid_data = (int*) data;
     std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
   }
@@ -432,29 +393,12 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   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));
+                                                    // 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);
@@ -471,11 +415,102 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
 
   // 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.");
+  ERRORR(rval, "Failed to get global id tag iterator on local edges.");
   assert(count == (int) nLocalEdges);
   gid_data = (int*) data;
   std::copy(localGidEdges.begin(), localGidEdges.end(), gid_data);
 
+  EntityHandle start_element = 0;
+  if (noMixedElements) {
+    // Only one group of cells (each cell is represented by a polygon with maxEdgesPerCell edges)
+    numCellGroups = 1;
+
+    // Create cells and set connectivity array with proper local vertices handles
+    EntityHandle* conn_arr_local_cells = NULL;
+    rval = _readNC->readMeshIface->get_element_connect(nLocalCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_local_cells,
+                                                      // Might have to create gather mesh later
+                                                      (create_gathers ? nLocalCells + nCells : nLocalCells));
+    ERRORR(rval, "Couldn't create local cells in MPAS mesh.");
+    Range local_cell_range(start_element, start_element + nLocalCells - 1);
+    tmp_range.insert(start_element, start_element + nLocalCells - 1);
+    faces.insert(start_element, start_element + nLocalCells - 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 global id tag iterator on local cells.");
+    assert(count == nLocalCells);
+    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];
+        conn_arr_local_cells[cell_idx * maxEdgesPerCell + i] = vert_handles[global_vert_id];
+      }
+
+      // Padding: fill connectivity array with last vertex handle
+      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;
+    }
+  } // if (noMixedElements)
+  else {
+    // 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 num_edges = num_edges_on_local_cells[i];
+      local_cells_with_n_edges[num_edges].push_back(start_cell_idx + 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();
+
+    // For each non-empty cell group, create cells and set connectivity array with proper local vertices handles
+    EntityHandle* conn_arr_local_cells_with_n_edges[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_cells = local_cells_with_n_edges[num_edges_per_cell].size();
+
+      rval = _readNC->readMeshIface->get_element_connect(num_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
+                                                         conn_arr_local_cells_with_n_edges[num_edges_per_cell], 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 global id tag iterator on local cells.");
+      assert(count == num_cells);
+      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);
+
+      for (int j = 0; j < num_cells; j++) {
+        int cell_idx = local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index
+        if (numCellGroups > 1)
+          cellHandleToGlobalID[start_element + j] = cell_idx;
+        cell_idx -= start_cell_idx; // Local cell index
+        for (int k = 0; k < num_edges_per_cell; k++) {
+          EntityHandle global_vert_id = vertices_on_local_cells[cell_idx * maxEdgesPerCell + k];
+          conn_arr_local_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] = vert_handles[global_vert_id];
+        }
+      }
+    } // for (int i = 0; i < numCellGroups; i++)
+  }
+
+  // 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.");
+
   // 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.");
@@ -487,7 +522,7 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
 
     // Create gather vertices
     arrays.clear();
-    // Don't need to specify allocation number here, because we know enough verts were created before
+    // Don't need to specify allocation number here, because we know enough vertices 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);
@@ -503,7 +538,7 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
 
     // 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..");
+    ERRORR(rval, "Failed to get global id tag iterator on gather vertices.");
     assert(count == nVertices);
     gid_data = (int*) data;
     for (int j = 1; j <= nVertices; j++)
@@ -511,7 +546,7 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
     // 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.");
+      ERRORR(rval, "Failed to get file id tag iterator on gather vertices.");
       assert(count == nVertices);
       gid_data = (int*) data;
       for (int j = 1; j <= nVertices; j++)
@@ -537,12 +572,28 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
     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
+
+    // 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.");
+
     // Read vertices on each gather cell (connectivity)
-    std::vector<int> vertices_on_gather_cells(nCells * maxCellEdges);
+    std::vector<int> vertices_on_gather_cells(nCells * maxEdgesPerCell);
     tmp_starts_2[0] = 0;
     tmp_starts_2[1] = 0;
     tmp_counts_2[0] = nCells;
-    tmp_counts_2[1] = maxCellEdges;
+    tmp_counts_2[1] = maxEdgesPerCell;
 #ifdef PNETCDF_FILE
     // Enter independent I/O mode, since this read is only for the gather processor
     success = NCFUNC(begin_indep_data)(_fileId);
@@ -556,50 +607,58 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
     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
+    Range gather_cells_range;
+    if (noMixedElements) {
+      // Create gather cells
+      EntityHandle* conn_arr_gather_cells;
+      // Don't need to specify allocation number here, because we know enough cells were created before
+      rval = _readNC->readMeshIface->get_element_connect(nCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_gather_cells);
+      ERRORR(rval, "Couldn't create cells in MPAS mesh for gather set.");
+      gather_cells_range.insert(start_element, start_element + nCells - 1);
+
+      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 verts start
+          conn_arr_gather_cells[cell_idx * maxEdgesPerCell + i] = (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;
+      }
     }
+    else {
+      // 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
+      }
 
-    // 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 cells
+      EntityHandle* conn_arr_gather_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
+      for (int num_edges_per_cell = 3; num_edges_per_cell <= maxEdgesPerCell; num_edges_per_cell++) {
+        int num_cells = gather_cells_with_n_edges[num_edges_per_cell].size();
+        if (num_cells > 0) {
+          rval = _readNC->readMeshIface->get_element_connect(num_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
+                                                             conn_arr_gather_cells_with_n_edges[num_edges_per_cell], 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[num_edges_per_cell][j];
+            cell_idx--; // 1 based -> 0 based
+            for (int k = 0; k < num_edges_per_cell; k++)
+              // Connectivity array is shifted by where the gather verts start
+              conn_arr_gather_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
+                (start_vertex - 1) + vertices_on_gather_cells[cell_idx * maxEdgesPerCell + k];
+          }
         }
       }
     }
 
     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 +674,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 +725,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);
@@ -790,8 +849,10 @@ 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;
@@ -893,9 +954,9 @@ 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;
@@ -1030,9 +1091,9 @@ 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;

diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
index 789a0fb..2c97566 100644
--- a/src/io/NCHelperMPAS.hpp
+++ b/src/io/NCHelperMPAS.hpp
@@ -49,7 +49,7 @@ private:
 #endif
 
 private:
-  int maxCellEdges;
+  int maxEdgesPerCell;
   int numCellGroups;
   std::vector<int> verticesOnEdge;
   std::map<EntityHandle, int> cellHandleToGlobalID;

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index a27a89d..80ad2f1 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -24,7 +24,7 @@ ReadNC::ReadNC(Interface* impl) :
 #ifdef USE_MPI
   myPcomm(NULL),
 #endif
-  noMesh(false), noVars(false), spectralMesh(false), gatherSetRank(-1), myHelper(NULL)
+  noMesh(false), noVars(false), spectralMesh(false), noMixedElements(false), gatherSetRank(-1), myHelper(NULL)
 {
   assert(impl != NULL);
   impl->query_interface(readMeshIface);
@@ -214,6 +214,10 @@ 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;
+
   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..eb470cd 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -207,6 +207,7 @@ private:
   bool noMesh;
   bool noVars;
   bool spectralMesh;
+  bool noMixedElements;
   int gatherSetRank;
 
   //! Helper class instance

diff --git a/test/io/read_mpas_nc.cpp b/test/io/read_mpas_nc.cpp
index d442577..597c752 100644
--- a/test/io/read_mpas_nc.cpp
+++ b/test/io/read_mpas_nc.cpp
@@ -1,5 +1,6 @@
 #include "TestUtil.hpp"
 #include "moab/Core.hpp"
+#include "moab/ReadUtilIface.hpp"
 
 using namespace moab;
 
@@ -11,6 +12,7 @@ static const char example[] = "/io/mpasx1.642.t.2.nc";
 
 #ifdef USE_MPI
 #include "moab_mpi.h"
+#include "moab/ParallelComm.hpp"
 #endif
 
 void test_read_all();
@@ -18,6 +20,7 @@ void test_read_onevar();
 void test_read_onetimestep();
 void test_read_nomesh();
 void test_read_novars();
+void test_read_no_mixed_elements();
 
 ErrorCode get_options(std::string& opts);
 
@@ -30,7 +33,7 @@ int main(int argc, char* argv[])
   if (fail)
     return 1;
 #else
-  argv[0] = argv[argc-argc]; // To remove the warnings in serial mode about unused variables
+  argv[0] = argv[argc - argc]; // To remove the warnings in serial mode about unused variables
 #endif
 
   result += RUN_TEST(test_read_all);
@@ -38,6 +41,8 @@ int main(int argc, char* argv[])
   result += RUN_TEST(test_read_onetimestep);
   result += RUN_TEST(test_read_nomesh);
   result += RUN_TEST(test_read_novars);
+  // Test read option NO_MIXED_ELEMENTS
+  result += RUN_TEST(test_read_no_mixed_elements);
 
 #ifdef USE_MPI
   fail = MPI_Finalize();
@@ -50,8 +55,6 @@ int main(int argc, char* argv[])
 
 void test_read_all()
 {
-  const double eps = 1e-20;
-  double val[2];
   Core moab;
   Interface& mb = moab;
 
@@ -62,81 +65,93 @@ void test_read_all()
   rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check tags for vertex variable vorticity
-  Tag vorticity_tag0, vorticity_tag1;
-  rval = mb.tag_get_handle("vorticity0", 1, MB_TYPE_DOUBLE, vorticity_tag0);
-  CHECK_ERR(rval);
-  rval = mb.tag_get_handle("vorticity1", 1, MB_TYPE_DOUBLE, vorticity_tag1);
-  CHECK_ERR(rval);
-
-  // Get vertices (1280 edges)
-  Range verts;
-  rval = mb.get_entities_by_type(0, MBVERTEX, verts);
-  assert(rval == MB_SUCCESS);
-  CHECK_EQUAL((size_t)1280, verts.size());
-  CHECK_EQUAL((size_t)1, verts.psize());
-
-  // Check vorticity tag values on first two vertices
-  EntityHandle vert_ents[] = {verts[0], verts[1]};
-  rval = mb.tag_get_data(vorticity_tag0, &vert_ents[0], 2, val);
-  CHECK_REAL_EQUAL(1.1, val[0], eps);
-  CHECK_REAL_EQUAL(1.2, val[1], eps);
-  rval = mb.tag_get_data(vorticity_tag1, &vert_ents[0], 2, val);
-  CHECK_REAL_EQUAL(2.1, val[0], eps);
-  CHECK_REAL_EQUAL(2.2, val[1], eps);
-
-  // Check tags for edge variable u
-  Tag u_tag0, u_tag1;
-  rval = mb.tag_get_handle("u0", 1, MB_TYPE_DOUBLE, u_tag0);
-  CHECK_ERR(rval);
-  rval = mb.tag_get_handle("u1", 1, MB_TYPE_DOUBLE, u_tag1);
-  CHECK_ERR(rval);
-
-  // Get edges (1920 edges)
-  Range edges;
-  rval = mb.get_entities_by_type(0, MBEDGE, edges);
-  assert(rval == MB_SUCCESS);
-  CHECK_EQUAL((size_t)1920, edges.size());
-  CHECK_EQUAL((size_t)1, edges.psize());
-
-  // Check u tag values on two specified edges
-  EntityHandle edge_ents[] = {edges[5], edges[6]};
-  rval = mb.tag_get_data(u_tag0, &edge_ents[0], 2, val);
-  CHECK_REAL_EQUAL(1.113138721544778, val[0], eps);
-  CHECK_REAL_EQUAL(-1.113138721930009, val[1], eps);
-  rval = mb.tag_get_data(u_tag1, &edge_ents[0], 2, val);
-  CHECK_REAL_EQUAL(2.113138721544778, val[0], eps);
-  CHECK_REAL_EQUAL(-2.113138721930009, val[1], eps);
-
-  // Check tags for cell variable ke
-  Tag ke_tag0, ke_tag1;
-  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
-  CHECK_ERR(rval);
-  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
-  CHECK_ERR(rval);
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  procs = pcomm->proc_config().proc_size();
+#endif
 
-  // Get cells (12 pentagons and 630 hexagons)
-  Range cells;
-  rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
-  assert(rval == MB_SUCCESS);
-  CHECK_EQUAL((size_t)642, cells.size());
+  // Make check runs this test in one processor
+  if (1 == procs) {
+    // Check tags for vertex variable vorticity
+    Tag vorticity_tag0, vorticity_tag1;
+    rval = mb.tag_get_handle("vorticity0", 1, MB_TYPE_DOUBLE, vorticity_tag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("vorticity1", 1, MB_TYPE_DOUBLE, vorticity_tag1);
+    CHECK_ERR(rval);
+
+    // Get vertices (1280 edges)
+    Range verts;
+    rval = mb.get_entities_by_type(0, MBVERTEX, verts);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)1280, verts.size());
+    CHECK_EQUAL((size_t)1, verts.psize());
+
+    const double eps = 1e-20;
+    double val[2];
+
+    // Check vorticity tag values on first two vertices
+    EntityHandle vert_ents[] = {verts[0], verts[1]};
+    rval = mb.tag_get_data(vorticity_tag0, &vert_ents[0], 2, val);
+    CHECK_REAL_EQUAL(1.1, val[0], eps);
+    CHECK_REAL_EQUAL(1.2, val[1], eps);
+    rval = mb.tag_get_data(vorticity_tag1, &vert_ents[0], 2, val);
+    CHECK_REAL_EQUAL(2.1, val[0], eps);
+    CHECK_REAL_EQUAL(2.2, val[1], eps);
+
+    // Check tags for edge variable u
+    Tag u_tag0, u_tag1;
+    rval = mb.tag_get_handle("u0", 1, MB_TYPE_DOUBLE, u_tag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("u1", 1, MB_TYPE_DOUBLE, u_tag1);
+    CHECK_ERR(rval);
+
+    // Get edges (1920 edges)
+    Range edges;
+    rval = mb.get_entities_by_type(0, MBEDGE, edges);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)1920, edges.size());
+    CHECK_EQUAL((size_t)1, edges.psize());
+
+    // Check u tag values on two specified edges
+    EntityHandle edge_ents[] = {edges[5], edges[6]};
+    rval = mb.tag_get_data(u_tag0, &edge_ents[0], 2, val);
+    CHECK_REAL_EQUAL(1.113138721544778, val[0], eps);
+    CHECK_REAL_EQUAL(-1.113138721930009, val[1], eps);
+    rval = mb.tag_get_data(u_tag1, &edge_ents[0], 2, val);
+    CHECK_REAL_EQUAL(2.113138721544778, val[0], eps);
+    CHECK_REAL_EQUAL(-2.113138721930009, val[1], eps);
+
+    // Check tags for cell variable ke
+    Tag ke_tag0, ke_tag1;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+    CHECK_ERR(rval);
+
+    // Get cells (12 pentagons and 630 hexagons)
+    Range cells;
+    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)642, cells.size());
 #ifdef USE_MPI
-  // If MOAB is compiled parallel, sequence size requested are increased
-  // by a factor of 1.5, to allow for ghosts. This will introduce a gap
-  // between the two face sequences.
-  CHECK_EQUAL((size_t)2, cells.psize());
+    // If MOAB is compiled parallel, sequence size requested are increased
+    // by a factor of 1.5, to allow for ghosts. This will introduce a gap
+    // between the two face sequences.
+    CHECK_EQUAL((size_t)2, cells.psize());
 #else
-  CHECK_EQUAL((size_t)1, cells.psize());
+    CHECK_EQUAL((size_t)1, cells.psize());
 #endif
 
-  // Check ke tag values on first pentagon and first hexagon
-  EntityHandle cell_ents[] = {cells[0], cells[12]};
-  rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-  CHECK_REAL_EQUAL(1.5, val[0], eps);
-  CHECK_REAL_EQUAL(1.6, val[1], eps);
-  rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-  CHECK_REAL_EQUAL(2.5, val[0], eps);
-  CHECK_REAL_EQUAL(2.6, val[1], eps);
+    // Check ke tag values on first pentagon and first hexagon
+    EntityHandle cell_ents[] = {cells[0], cells[12]};
+    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(1.5, val[0], eps);
+    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(2.5, val[0], eps);
+    CHECK_REAL_EQUAL(2.6, val[1], eps);
+  }
 }
 
 void test_read_onevar() 
@@ -148,15 +163,75 @@ void test_read_onevar()
   CHECK_ERR(rval);
 
   opts += std::string(";VARIABLE=ke");
+  // Create gather set
+  opts += std::string(";GATHER_SET=");
   rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tags
-  Tag ke_tag0, ke_tag1;
-  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
-  CHECK_ERR(rval);
-  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
-  CHECK_ERR(rval);
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  procs = pcomm->proc_config().proc_size();
+#endif
+
+  // Make check runs this test in one processor
+  if (1 == procs) {
+    // Check for proper tags
+    Tag ke_tag0, ke_tag1;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+    CHECK_ERR(rval);
+
+    // Get cells (12 pentagons and 630 hexagons)
+    Range cells;
+    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)1284, cells.size()); // Gather set cells included
+#ifdef USE_MPI
+    // If MOAB is compiled parallel, sequence size requested are increased
+    // by a factor of 1.5, to allow for ghosts. This will introduce a gap
+    // between the two face sequences.
+    CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
+#else
+    CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
+#endif
+
+    // Get gather set
+    EntityHandle gather_set;
+    ReadUtilIface* readUtilIface;
+    mb.query_interface(readUtilIface);
+    rval = readUtilIface->get_gather_set(gather_set);
+    CHECK_ERR(rval);
+
+    // Get gather set entities
+    Range gather_ents;
+    rval = mb.get_entities_by_handle(gather_set, gather_ents);
+    CHECK_ERR(rval);
+
+    // Remove gather set cells
+    cells = subtract(cells, gather_ents);
+    CHECK_EQUAL((size_t)642, cells.size()); // Gather set cells excluded
+#ifdef USE_MPI
+    // If MOAB is compiled parallel, sequence size requested are increased
+    // by a factor of 1.5, to allow for ghosts. This will introduce a gap
+    // between the two face sequences.
+    CHECK_EQUAL((size_t)2, cells.psize()); // Gather set cells excluded
+#else
+    CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded
+#endif
+
+    // Check ke tag values on first pentagon and first hexagon
+    const double eps = 1e-20;
+    double val[2];
+    EntityHandle cell_ents[] = {cells[0], cells[12]};
+    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(1.5, val[0], eps);
+    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(2.5, val[0], eps);
+    CHECK_REAL_EQUAL(2.6, val[1], eps);
+  }
 }
 
 void test_read_onetimestep()
@@ -196,7 +271,7 @@ void test_read_nomesh()
   opts = orig + std::string(";TIMESTEP=0");
   rval = mb.load_file(example, &set, opts.c_str());
   CHECK_ERR(rval);
-  
+
   // Check for proper tags
   Tag ke_tag0, ke_tag1;
   rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
@@ -261,6 +336,55 @@ void test_read_novars()
   CHECK_ERR(rval);
 }
 
+void test_read_no_mixed_elements()
+{
+  Core moab;
+  Interface& mb = moab;
+  std::string opts;
+  ErrorCode rval = get_options(opts);
+  CHECK_ERR(rval);
+
+  opts += std::string(";NO_MIXED_ELEMENTS;VARIABLE=ke");
+  rval = mb.load_file(example, NULL, opts.c_str());
+  CHECK_ERR(rval);
+
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  procs = pcomm->proc_config().proc_size();
+#endif
+
+  // Make check runs this test in one processor
+  if (1 == procs) {
+    // Check for proper tags
+    Tag ke_tag0, ke_tag1;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+    CHECK_ERR(rval);
+
+    // Get cells (12 pentagons and 630 hexagons)
+    Range cells;
+    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)642, cells.size());
+    // Only one group of cells (each cell is actually represented by a 10-vertex polygon)
+    CHECK_EQUAL((size_t)1, cells.psize());
+
+    const double eps = 1e-20;
+    double val[2];
+
+    // Check ke tag values on first pentagon and first hexagon
+    EntityHandle cell_ents[] = {cells[0], cells[12]};
+    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(1.5, val[0], eps);
+    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(2.5, val[0], eps);
+    CHECK_REAL_EQUAL(2.6, val[1], eps);
+  }
+}
+
 ErrorCode get_options(std::string &opts) 
 {
 #ifdef USE_MPI

diff --git a/test/io/read_ucd_nc.cpp b/test/io/read_ucd_nc.cpp
index bd16ec4..12ca977 100644
--- a/test/io/read_ucd_nc.cpp
+++ b/test/io/read_ucd_nc.cpp
@@ -85,14 +85,6 @@ void test_read_onevar()
   rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tags
-  Tag Ttag0, Ttag1;
-  rval = mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
-  CHECK_ERR(rval);
-
-  rval = mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
-  CHECK_ERR(rval);
-
   // Check values of tag T0 at some strategically chosen places below
   int procs = 1;
 #ifdef USE_MPI
@@ -102,6 +94,13 @@ void test_read_onevar()
 
   // Make check runs this test in one processor
   if (1 == procs) {
+    // Check for proper tags
+    Tag Ttag0, Ttag1;
+    rval = mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+    CHECK_ERR(rval);
+    rval = mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+    CHECK_ERR(rval);
+
     // Get vertices
     Range verts;
     rval = mb.get_entities_by_type(0, MBVERTEX, verts);
@@ -131,9 +130,10 @@ void test_read_onevar()
     CHECK_ERR(rval);
     CHECK_EQUAL((size_t)count, verts.size());
 
-    // Check first level values at some vertices
     const double eps = 0.0001;
     double* data = (double*) Tbuf;
+
+    // Check first level values at some vertices
     CHECK_REAL_EQUAL(233.1136, data[0 * 26], eps); // First vert
     CHECK_REAL_EQUAL(236.1505, data[1728 * 26], eps); // Median vert
     CHECK_REAL_EQUAL(235.7722, data[1729 * 26], eps); // Median vert

diff --git a/test/parallel/mpastrvpart.cpp b/test/parallel/mpastrvpart.cpp
index 5cacd2c..2b86f61 100644
--- a/test/parallel/mpastrvpart.cpp
+++ b/test/parallel/mpastrvpart.cpp
@@ -12,9 +12,11 @@ static const char example[] = STRINGIFY(MESHDIR) "/io/mpasx1.642.t.2.nc";
 #endif
 
 void test_read_parallel_mpas_trivial();
-void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges);
-
+void test_read_parallel_mpas_trivial_no_mixed_elements();
+void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
+                        int num_cells, bool test_nb_cells, bool mixed_elements);
 void test_multiple_loads_of_same_file();
+void test_multiple_loads_of_same_file_no_mixed_elements();
 
 std::string partition_method;
 
@@ -24,7 +26,9 @@ int main(int argc, char* argv[])
   int result = 0;
 
   result += RUN_TEST(test_read_parallel_mpas_trivial);
+  result += RUN_TEST(test_read_parallel_mpas_trivial_no_mixed_elements);
   result += RUN_TEST(test_multiple_loads_of_same_file);
+  result += RUN_TEST(test_multiple_loads_of_same_file_no_mixed_elements);
 
   MPI_Finalize();
   return result;
@@ -33,10 +37,17 @@ int main(int argc, char* argv[])
 void test_read_parallel_mpas_trivial()
 {
   partition_method = std::string(";PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS");
-  test_read_parallel(1280, true, 1920, true);
+  test_read_parallel(1280, true, 1920, true, 642, true, true);
 }
-  
-void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges)
+
+void test_read_parallel_mpas_trivial_no_mixed_elements()
+{
+  partition_method = std::string(";PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS;NO_MIXED_ELEMENTS");
+  test_read_parallel(1280, true, 1920, true, 642, true, false);
+}
+
+void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
+                        int num_cells, bool test_nb_cells, bool mixed_elements)
 {
   Core moab;
   Interface& mb = moab;
@@ -82,43 +93,6 @@ void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool t
       CHECK_EQUAL(160, my_verts_num); // Not owned vertices excluded
   }
 
-  if (0 == rank) {
-    // Get gather set
-    EntityHandle gather_set;
-    ReadUtilIface* readUtilIface;
-    rval = mb.query_interface(readUtilIface);
-    CHECK_ERR(rval);
-    rval = readUtilIface->get_gather_set(gather_set);
-    CHECK_ERR(rval);
-
-    // Get gather set entities
-    Range gather_ents;
-    rval = mb.get_entities_by_handle(gather_set, gather_ents);
-    CHECK_ERR(rval);
-
-    // Remove gather set vertices in processor 0
-    verts = subtract(verts, gather_ents);
-  }
-
-  my_verts_num = verts.size();
-  if (test_nb_nodes && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(1120, my_verts_num); // Gather set vertices excluded
-    else if (1 == rank)
-      CHECK_EQUAL(160, my_verts_num); // Not owned vertices excluded
-  }
-
-  std::cout << "proc: " << rank << " verts:" << my_verts_num << "\n";
-
-  int total_verts;
-  MPI_Reduce(&my_verts_num, &total_verts, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
-  if (0 == rank)
-  {
-    std::cout << "total vertices: " << total_verts << "\n";
-    if (test_nb_nodes)
-      CHECK_EQUAL(total_verts, num_verts);
-  }
-
   // Get the total # owned edges
   Range edges;
   rval = mb.get_entities_by_type(0, MBEDGE, edges);
@@ -143,6 +117,44 @@ void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool t
       CHECK_EQUAL(482, my_edges_num); // Not owned edges excluded
   }
 
+  // Get the total # owned cells
+  Range cells;
+  rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+  CHECK_ERR(rval);
+
+  int my_cells_num = cells.size();
+  if (test_nb_cells && 2 == procs) {
+    if (0 == rank) {
+      CHECK_EQUAL(963, my_cells_num); // Gather set cells included
+      if (mixed_elements)
+        CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
+      else
+        CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
+    }
+    else if (1 == rank) {
+      CHECK_EQUAL(321, my_cells_num); // Not owned cells included
+      CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells included
+    }
+  }
+
+   rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+   CHECK_ERR(rval);
+
+   my_cells_num = cells.size();
+   if (test_nb_cells && 2 == procs) {
+     if (0 == rank) {
+       CHECK_EQUAL(963, my_cells_num); // Gather set cells included
+       if (mixed_elements)
+         CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
+       else
+         CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
+     }
+     else if (1 == rank) {
+       CHECK_EQUAL(321, my_cells_num); // Not owned cells excluded
+       CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells excluded
+     }
+   }
+
   if (0 == rank) {
     // Get gather set
     EntityHandle gather_set;
@@ -157,8 +169,32 @@ void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool t
     rval = mb.get_entities_by_handle(gather_set, gather_ents);
     CHECK_ERR(rval);
 
+    // Remove gather set vertices in processor 0
+    verts = subtract(verts, gather_ents);
+
     // Remove gather set edges in processor 0
     edges = subtract(edges, gather_ents);
+
+    // Remove gather set cells in processor 0
+    cells = subtract(cells, gather_ents);
+  }
+
+  my_verts_num = verts.size();
+  if (test_nb_nodes && 2 == procs) {
+    if (0 == rank)
+      CHECK_EQUAL(1120, my_verts_num); // Gather set vertices excluded
+    else if (1 == rank)
+      CHECK_EQUAL(160, my_verts_num); // Not owned vertices excluded
+  }
+
+  std::cout << "proc: " << rank << " verts:" << my_verts_num << "\n";
+
+  int total_verts;
+  MPI_Reduce(&my_verts_num, &total_verts, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
+  if (0 == rank) {
+    std::cout << "total vertices: " << total_verts << "\n";
+    if (test_nb_nodes)
+      CHECK_EQUAL(total_verts, num_verts);
   }
 
   my_edges_num = edges.size();
@@ -173,13 +209,37 @@ void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool t
 
   int total_edges;
   MPI_Reduce(&my_edges_num, &total_edges, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
-  if (0 == rank)
-  {
+  if (0 == rank) {
     std::cout << "total edges: " << total_edges << "\n";
     if (test_nb_edges)
       CHECK_EQUAL(total_edges, num_edges);
   }
 
+  my_cells_num = cells.size();
+  if (test_nb_cells && 2 == procs) {
+    if (0 == rank) {
+      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded
+      if (mixed_elements)
+        CHECK_EQUAL((size_t)2, cells.psize()); // Gather set cells excluded
+      else
+        CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded
+    }
+    else if (1 == rank) {
+      CHECK_EQUAL(321, my_cells_num); // Not owned cells excluded
+      CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells excluded
+    }
+  }
+
+   std::cout << "proc: " << rank << " cells:" << my_cells_num << "\n";
+
+   int total_cells;
+   MPI_Reduce(&my_cells_num, &total_cells, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
+   if (0 == rank) {
+     std::cout << "total cells: " << total_cells << "\n";
+     if (test_nb_cells)
+       CHECK_EQUAL(total_cells, num_cells);
+   }
+
   std::string write_options("PARALLEL=WRITE_PART;");
   mb.write_file("test_mpas.h5m", NULL, write_options.c_str());
 }
@@ -220,13 +280,44 @@ void test_multiple_loads_of_same_file()
     rval = mb.get_entities_by_type(0, MBVERTEX, verts);
     CHECK_ERR(rval);
 
+    Range edges;
+    rval = mb.get_entities_by_type(0, MBEDGE, edges);
+    CHECK_ERR(rval);
+
+    Range cells;
+    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    CHECK_ERR(rval);
+
     int my_verts_num = verts.size();
-    if (0 == rank)
+    int my_edges_num = edges.size();
+    int my_cells_num = cells.size();
+
+    if (0 == rank) {
       CHECK_EQUAL(1120, my_verts_num);
-    else if (1 == rank)
+      CHECK_EQUAL(1438, my_edges_num);
+      CHECK_EQUAL(321, my_cells_num);
+      CHECK_EQUAL((size_t)2, cells.psize());
+
+      const double eps = 1e-20;
+      double val[2];
+
+      // Check tag for cell variable ke at timestep 0
+      Tag ke_tag0;
+      rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+      CHECK_ERR(rval);
+
+      // Check ke0 tag values on first pentagon and first hexagon
+      EntityHandle cell_ents[] = {cells[0], cells[12]};
+      rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+      CHECK_REAL_EQUAL(1.5, val[0], eps);
+      CHECK_REAL_EQUAL(1.6, val[1], eps);
+    }
+    else if (1 == rank) {
       CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included
+      CHECK_EQUAL(3364, my_edges_num); // Gather set edges included; Not owned edges included
+      CHECK_EQUAL(963, my_cells_num); // Gather set cells included; Not owned cells included
+      CHECK_EQUAL((size_t)3, cells.psize()); // Gather set cells included; Not owned cells included
 
-    if (1 == rank) {
       // Get gather set
       EntityHandle gather_set;
       ReadUtilIface* readUtilIface;
@@ -242,12 +333,125 @@ void test_multiple_loads_of_same_file()
 
       // Remove gather set vertices in processor 1
       verts = subtract(verts, gather_ents);
+      my_verts_num = verts.size();
+      CHECK_EQUAL(1122, my_verts_num); // Gather set vertices excluded; Not owned vertices included
+
+      // Remove gather set edges in processor 1
+      edges = subtract(edges, gather_ents);
+      my_edges_num = edges.size();
+      CHECK_EQUAL(1444, my_edges_num); // Gather set edges excluded; Not owned edges included
+
+      // Remove gather set cells in processor 1
+      cells = subtract(cells, gather_ents);
+      my_cells_num = cells.size();
+      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded; Not owned cells included
+      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded; Not owned cells included
     }
+  }
+}
 
-    my_verts_num = verts.size();
-    if (0 == rank)
+void test_multiple_loads_of_same_file_no_mixed_elements()
+{
+  Core moab;
+  Interface& mb = moab;
+  EntityHandle file_set;
+  ErrorCode rval;
+  rval = mb.create_meshset(MESHSET_SET, file_set);
+  CHECK_ERR(rval);
+
+  // Read first only header information, no mesh, no variable
+  std::string opts("PARALLEL=READ_PART;PARTITION;NOMESH;VARIABLE=;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS");
+  rval = mb.load_file(example, &file_set, opts.c_str());
+  CHECK_ERR(rval);
+
+  // Create mesh, no variable
+  opts="PARALLEL=READ_PART;PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS;VARIABLE=";
+  // Create gather set in processor 1
+  opts += std::string(";GATHER_SET=1");
+  rval = mb.load_file(example, &file_set, opts.c_str());
+  CHECK_ERR(rval);
+
+  // Read variable ke at timestep 0, no mesh
+  opts = "PARALLEL=READ_PART;PARTITION;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS;NOMESH;VARIABLE=ke;TIMESTEP=0";
+  rval = mb.load_file(example, &file_set, opts.c_str());
+  CHECK_ERR(rval);
+
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  int procs = pcomm->proc_config().proc_size();
+  int rank = pcomm->proc_config().proc_rank();
+
+  // Make check runs this test in two processors
+  if (2 == procs) {
+    Range verts;
+    rval = mb.get_entities_by_type(0, MBVERTEX, verts);
+    CHECK_ERR(rval);
+
+    Range edges;
+    rval = mb.get_entities_by_type(0, MBEDGE, edges);
+    CHECK_ERR(rval);
+
+    Range cells;
+    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    CHECK_ERR(rval);
+
+    int my_verts_num = verts.size();
+    int my_edges_num = edges.size();
+    int my_cells_num = cells.size();
+
+    if (0 == rank) {
       CHECK_EQUAL(1120, my_verts_num);
-    else if (1 == rank)
+      CHECK_EQUAL(1438, my_edges_num);
+      CHECK_EQUAL(321, my_cells_num);
+      CHECK_EQUAL((size_t)1, cells.psize());
+
+      const double eps = 1e-20;
+      double val[2];
+
+      // Check tag for cell variable ke at timestep 0
+      Tag ke_tag0;
+      rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+      CHECK_ERR(rval);
+
+      // Check ke0 tag values on first pentagon and first hexagon
+      EntityHandle cell_ents[] = {cells[0], cells[12]};
+      rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+      CHECK_REAL_EQUAL(1.5, val[0], eps);
+      CHECK_REAL_EQUAL(1.6, val[1], eps);
+    }
+    else if (1 == rank) {
+      CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included
+      CHECK_EQUAL(3364, my_edges_num); // Gather set edges included; Not owned edges included
+      CHECK_EQUAL(963, my_cells_num); // Gather set cells included; Not owned cells included
+      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included; Not owned cells included
+
+      // Get gather set
+      EntityHandle gather_set;
+      ReadUtilIface* readUtilIface;
+      rval = mb.query_interface(readUtilIface);
+      CHECK_ERR(rval);
+      rval = readUtilIface->get_gather_set(gather_set);
+      CHECK_ERR(rval);
+
+      // Get gather set entities
+      Range gather_ents;
+      rval = mb.get_entities_by_handle(gather_set, gather_ents);
+      CHECK_ERR(rval);
+
+      // Remove gather set vertices in processor 1
+      verts = subtract(verts, gather_ents);
+      my_verts_num = verts.size();
       CHECK_EQUAL(1122, my_verts_num); // Gather set vertices excluded; Not owned vertices included
+
+      // Remove gather set edges in processor 1
+      edges = subtract(edges, gather_ents);
+      my_edges_num = edges.size();
+      CHECK_EQUAL(1444, my_edges_num); // Gather set edges excluded; Not owned edges included
+
+      // Remove gather set cells in processor 1
+      cells = subtract(cells, gather_ents);
+      my_cells_num = cells.size();
+      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded; Not owned cells included
+      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded; Not owned cells included
+    }
   }
 }

diff --git a/test/parallel/ucdtrvpart.cpp b/test/parallel/ucdtrvpart.cpp
index 720df36..0800b4c 100644
--- a/test/parallel/ucdtrvpart.cpp
+++ b/test/parallel/ucdtrvpart.cpp
@@ -169,10 +169,9 @@ void test_multiple_loads_of_same_file()
     int my_num = verts.size();
     if (0 == rank)
       CHECK_EQUAL(1825, my_num);
-    else if (1 == rank)
+    else if (1 == rank) {
       CHECK_EQUAL(5283, my_num); // Gather set vertices included; Not owned vertices included
 
-    if (1 == rank) {
       // Get gather set
       EntityHandle gather_set;
       ReadUtilIface* readUtilIface;
@@ -188,13 +187,9 @@ void test_multiple_loads_of_same_file()
 
       // Remove gather set vertices in processor 1
       verts = subtract(verts, gather_ents);
-    }
-
-    my_num = verts.size();
-    if (0 == rank)
-      CHECK_EQUAL(1825, my_num);
-    else if (1 == rank)
+      my_num = verts.size();
       CHECK_EQUAL(1825, my_num); // Gather set vertices excluded; Not owned vertices included
+    }
 
     Tag Ttag0;
     rval = mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0, MB_TAG_DENSE);

diff --git a/tools/mbzoltan/MBZoltan.cpp b/tools/mbzoltan/MBZoltan.cpp
index 1ec6757..45b8a35 100644
--- a/tools/mbzoltan/MBZoltan.cpp
+++ b/tools/mbzoltan/MBZoltan.cpp
@@ -254,7 +254,8 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
                                         const int obj_weight,
                                         const int edge_weight,
                                         const bool part_surf,
-                                        const bool ghost) 
+                                        const bool ghost,
+                                        const bool print_time)
 {
     // should only be called in serial
   if (mbpc->proc_config().proc_size() != 1) {
@@ -262,7 +263,7 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
               << std::endl;
     return MB_FAILURE;
   }
-  
+  clock_t t = clock();
   if (NULL != zmethod && strcmp(zmethod, "RR") && strcmp(zmethod, "RCB") && strcmp(zmethod, "RIB") &&
       strcmp(zmethod, "HSFC") && strcmp(zmethod, "Hypergraph") &&
       strcmp(zmethod, "PHG") && strcmp(zmethod, "PARMETIS") &&
@@ -274,6 +275,10 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
     return MB_FAILURE;
   }
 
+  bool part_geom = false;
+  if ( 0==  strcmp(zmethod, "RR") || 0== strcmp(zmethod, "RCB") || 0== strcmp(zmethod, "RIB")
+      || 0==strcmp(zmethod, "HSFC") )
+    part_geom=true; // so no adjacency / edges needed
   std::vector<double> pts; // x[0], y[0], z[0], ... from MOAB
   std::vector<int> ids; // point ids from MOAB
   std::vector<int> adjs, length, parts;
@@ -321,7 +326,7 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
   
   if (part_geom_mesh_size < 0.) {
     //if (!part_geom) {
-    result = assemble_graph(part_dim, pts, ids, adjs, length, elems); RR;
+       result = assemble_graph(part_dim, pts, ids, adjs, length, elems, part_geom); RR;
   }
   else {
 #ifdef CGM
@@ -347,20 +352,29 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
     }
 #endif
   }
-  
+  if (print_time)
+  {
+    std::cout << " time to assemble graph: " << (clock() - t) / (double) CLOCKS_PER_SEC  << "s. \n";
+    t = clock();
+  }
   double* o_wgt = NULL;
   double* e_wgt = NULL;
   if (obj_weights.size() > 0) o_wgt = &obj_weights[0];
   if (edge_weights.size() > 0) e_wgt = &edge_weights[0];
     
   myNumPts = mbInitializePoints((int)ids.size(), &pts[0], &ids[0], &adjs[0],
-                                &length[0], o_wgt, e_wgt, &parts[0]);
+                                &length[0], o_wgt, e_wgt, &parts[0], part_geom);
   
 
   // Initialize Zoltan.  This is a C call.  The simple C++ code 
   // that creates Zoltan objects does not keep track of whether 
   // Zoltan_Initialize has been called.
 
+  if (print_time)
+  {
+    std::cout << " time to initialize points: " << (clock() - t) / (double) CLOCKS_PER_SEC  << "s. \n";
+    t = clock();
+  }
   float version;
 
   std::cout << "Initializing zoltan..." << std::endl;
@@ -458,6 +472,11 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
                               assign_procs, assign_parts);
   if (ZOLTAN_OK != retval) return MB_FAILURE;
   
+  if (print_time)
+  {
+    std::cout << " time to LB_partition " << (clock() - t) / (double) CLOCKS_PER_SEC  << "s. \n";
+    t = clock();
+  }
   // take results & write onto MOAB partition sets
   std::cout << "Saving partition information to MOAB..." << std::endl;
   
@@ -473,6 +492,12 @@ ErrorCode MBZoltan::partition_mesh_geom(const double part_geom_mesh_size,
 #endif
   }
 
+  if (print_time)
+  {
+    std::cout << " time to write partition in memory " <<(clock() - t) / (double) CLOCKS_PER_SEC  << "s. \n";
+    t = clock();
+  }
+
   if (MB_SUCCESS != result) return result;
 
 
@@ -550,7 +575,7 @@ ErrorCode MBZoltan::assemble_graph(const int dimension,
                                    std::vector<int> &moab_ids,
                                    std::vector<int> &adjacencies, 
                                    std::vector<int> &length,
-                                   Range &elems) 
+                                   Range &elems, bool  part_geom)
 {
     // assemble a graph with vertices equal to elements of specified dimension, edges
     // signified by list of other elements to which an element is connected
@@ -580,21 +605,24 @@ ErrorCode MBZoltan::assemble_graph(const int dimension,
   
   for (Range::iterator rit = elems.begin(); rit != elems.end(); rit++) {
 
-      // get bridge adjacencies
-    adjs.clear();
-    result = mtu.get_bridge_adjacencies(*rit, (dimension > 0 ? dimension-1 : 3), 
-                                        dimension, adjs); RR;
 
-      // get the graph vertex ids of those
-    if (!adjs.empty()) {
-      assert(adjs.size() < 5*MAX_SUB_ENTITIES);
-      result = mbImpl->tag_get_data(gid, adjs, neighbors); RR;
-    }
+    if (!part_geom)
+    {
+      // get bridge adjacencies
+      adjs.clear();
+      result = mtu.get_bridge_adjacencies(*rit, (dimension > 0 ? dimension-1 : 3),
+                                          dimension, adjs); RR;
 
-      // copy those into adjacencies vector
-    length.push_back((int)adjs.size());
-    std::copy(neighbors, neighbors+adjs.size(), std::back_inserter(adjacencies));
+        // get the graph vertex ids of those
+      if (!adjs.empty()) {
+        assert(adjs.size() < 5*MAX_SUB_ENTITIES);
+        result = mbImpl->tag_get_data(gid, adjs, neighbors); RR;
+      }
 
+        // copy those into adjacencies vector
+      length.push_back((int)adjs.size());
+      std::copy(neighbors, neighbors+adjs.size(), std::back_inserter(adjacencies));
+    }
 
       // get average position of vertices
     result = mtu.get_average_position(*rit, avg_position); RR;
@@ -1305,7 +1333,7 @@ ErrorCode MBZoltan::write_partition(const int nparts,
                                     Range &elems, 
                                     const int *assignment,
                                     const bool write_as_sets,
-                                    const bool write_as_tags) 
+                                    const bool write_as_tags)
 {
   ErrorCode result;
 
@@ -1347,10 +1375,9 @@ ErrorCode MBZoltan::write_partition(const int nparts,
         result = mbImpl->delete_entities(&old_set, 1); RR;
       }
     }
-  
-      // assign partition sets to vector
+    // assign partition sets to vector
     partSets.swap(tagged_sets);
-  
+
       // write a tag to those sets denoting they're partition sets, with a value of the
       // proc number
     int *dum_ids = new int[nparts];
@@ -1358,14 +1385,26 @@ ErrorCode MBZoltan::write_partition(const int nparts,
   
     result = mbImpl->tag_set_data(part_set_tag, partSets, dum_ids); RR;
 
-      // assign entities to the relevant sets
+    // assign entities to the relevant sets
     std::vector<EntityHandle> tmp_part_sets;
+    //int N = (int)elems.size();
     std::copy(partSets.begin(), partSets.end(), std::back_inserter(tmp_part_sets));
+    /*Range::reverse_iterator riter;
+    for (i = N-1, riter = elems.rbegin(); riter != elems.rend(); riter++, i--) {
+      int assigned_part = assignment[i];
+      part_ranges[assigned_part].insert(*riter);
+      //result = mbImpl->add_entities(tmp_part_sets[assignment[i]], &(*rit), 1); RR;
+    }*/
+
     Range::iterator rit;
     for (i = 0, rit = elems.begin(); rit != elems.end(); rit++, i++) {
       result = mbImpl->add_entities(tmp_part_sets[assignment[i]], &(*rit), 1); RR;
     }
-
+    /*for (i=0; i<nparts; i++)
+    {
+      result = mbImpl->add_entities(tmp_part_sets[i], part_ranges[i]); RR;
+    }
+    delete [] part_ranges;*/
       // check for empty sets, warn if there are any
     Range empty_sets;
     for (rit = partSets.begin(); rit != partSets.end(); rit++) {
@@ -1474,17 +1513,17 @@ void MBZoltan::SetOCTPART_Parameters(const char *oct_method)
 int MBZoltan::mbInitializePoints(int npts, double *pts, int *ids, 
                                  int *adjs, int *length,
                                  double *obj_weights, double *edge_weights,
-                                 int *parts)
+                                 int *parts, bool part_geom)
 {
   unsigned int i;
   int j;
-  int *numPts, *nborProcs;
+  int *numPts, *nborProcs = NULL;
   int sum, ptsPerProc, ptsAssigned, mySize;
   MPI_Status stat;
   double *sendPts;
   int *sendIds;
-  int *sendEdges;
-  int *sendNborId;
+  int *sendEdges = NULL;
+  int *sendNborId = NULL;
   int *sendProcs;
 
   if (mbpc->proc_config().proc_rank() == 0) {
@@ -1504,19 +1543,22 @@ int MBZoltan::mbInitializePoints(int npts, double *pts, int *ids,
     mySize = numPts[mbpc->proc_config().proc_rank()];
     sendPts = pts + (3 * numPts[0]);
     sendIds = ids + numPts[0];
-    sendEdges = length + numPts[0];
-    sum = 0;
+    sum = 0; // possible no adjacency sent
+    if (!part_geom)
+    {
+      sendEdges = length + numPts[0];
 
-    for (j = 0; j < numPts[0]; j++)
-      sum += length[j];
 
-    sendNborId = adjs + sum;
+      for (j = 0; j < numPts[0]; j++)
+        sum += length[j];
 
-    for (j = numPts[0]; j < npts; j++)
-      sum += length[j];
+      sendNborId = adjs + sum;
 
-    nborProcs = (int *)malloc(sizeof(int) * sum);
+      for (j = numPts[0]; j < npts; j++)
+        sum += length[j];
 
+      nborProcs = (int *)malloc(sizeof(int) * sum);
+    }
     for (j = 0; j < sum; j++)
       if ((i = adjs[j] / ptsPerProc) < mbpc->proc_config().proc_size())
         nborProcs[j] = i;

diff --git a/tools/mbzoltan/MBZoltan.hpp b/tools/mbzoltan/MBZoltan.hpp
index 269d9ae..4a0e999 100644
--- a/tools/mbzoltan/MBZoltan.hpp
+++ b/tools/mbzoltan/MBZoltan.hpp
@@ -112,7 +112,8 @@ using namespace moab;
                                   const int obj_weight = 0,
                                   const int edge_weight = 0,
                                   const bool part_surf = false,
-                                  const bool ghost = false);
+                                  const bool ghost = false,
+                                  const bool print_time = false);
     
     int get_mesh(std::vector<double> &pts, std::vector<int> &ids,
                  std::vector<int> &adjs, std::vector<int> &length,
@@ -198,7 +199,7 @@ using namespace moab;
                              std::vector<int> &moab_ids,
                              std::vector<int> &adjacencies, 
                              std::vector<int> &length,
-                             Range &elems);
+                             Range &elems, bool part_geom = false);
     
 #ifdef CGM
     std::map<int, int> body_vertex_map, surf_vertex_map;
@@ -234,7 +235,7 @@ using namespace moab;
                            int *adjs, int *length,
                            double *obj_weights = NULL,
                            double *edge_weights = NULL,
-                           int *parts = NULL);
+                           int *parts = NULL, bool part_geom = false);
 
 #ifdef CGM
     GeometryQueryTool *gti;

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/125ca3597f82/
Changeset:   125ca3597f82
Branch:      None
User:        danwu
Date:        2013-10-16 23:33:54
Summary:     Merged fathomteam/moab into master
Affected #:  8 files

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/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/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 42eeca0..45ce16e 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -14,11 +14,11 @@
 
 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)
-, maxEdgesPerCell(MAX_EDGES_PER_CELL)
+, maxEdgesPerCell(DEFAULT_MAX_EDGES_PER_CELL)
 , numCellGroups(0)
 {
 }
@@ -44,12 +44,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();
     maxEdgesPerCell = dimLens[idx];
-    if (maxEdgesPerCell > MAX_EDGES_PER_CELL) {
-      ERRORR(MB_FAILURE, "maxEdgesPerCell read from MPAS file has exceeded the limit");
+    if (maxEdgesPerCell > DEFAULT_MAX_EDGES_PER_CELL) {
+      ERRORR(MB_FAILURE, "maxEdgesPerCell read from the MPAS file header has exceeded DEFAULT_MAX_EDGES_PER_CELL.");
     }
   }
 
@@ -311,6 +311,20 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   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.");
 
+  // Get local maxEdgesPerCell on this proc
+  maxEdgesPerCell = *(std::max_element(num_edges_on_local_cells.begin(), num_edges_on_local_cells.end()));
+
+  // In parallel, do a MPI_Allreduce to get a common global maxEdgesPerCell used across all procs
+#ifdef USE_MPI
+  if (procs > 1) {
+    int global_max_edges_per_cell;
+    ParallelComm*& myPcomm = _readNC->myPcomm;
+    MPI_Allreduce(&maxEdgesPerCell, &global_max_edges_per_cell, 1, MPI_INTEGER, MPI_MAX, myPcomm->proc_config().proc_comm());
+    assert(maxEdgesPerCell <= global_max_edges_per_cell);
+    maxEdgesPerCell = global_max_edges_per_cell;
+  }
+#endif
+
   // Read vertices on each local cell (connectivity)
   int verticesOnCellVarId;
   success = NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCellVarId);
@@ -451,14 +465,16 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
       }
 
       // Padding: fill connectivity array with last vertex handle
-      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;
+      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;
+      }
     }
   } // if (noMixedElements)
   else {
     // Divide local cells into groups based on the number of edges
-    std::vector<int> local_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
+    std::vector<int> local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
     for (int i = 0; i < nLocalCells; i++) {
       int num_edges = num_edges_on_local_cells[i];
       local_cells_with_n_edges[num_edges].push_back(start_cell_idx + i); // Global cell index
@@ -472,7 +488,7 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
     numCellGroups = num_edges_on_cell_groups.size();
 
     // For each non-empty cell group, create cells and set connectivity array with proper local vertices handles
-    EntityHandle* conn_arr_local_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
+    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_cells = local_cells_with_n_edges[num_edges_per_cell].size();
@@ -630,14 +646,14 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
     }
     else {
       // Divide gather cells into groups based on the number of edges
-      std::vector<int> gather_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
+      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 cells
-      EntityHandle* conn_arr_gather_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
+      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_cells = gather_cells_with_n_edges[num_edges_per_cell].size();
         if (num_cells > 0) {

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/tools/mbcslam/Intx2Mesh.cpp b/tools/mbcslam/Intx2Mesh.cpp
index 6faa94a..d9db131 100644
--- a/tools/mbcslam/Intx2Mesh.cpp
+++ b/tools/mbcslam/Intx2Mesh.cpp
@@ -381,8 +381,12 @@ ErrorCode Intx2Mesh::intersect_meshes(EntityHandle mbset1, EntityHandle mbset2,
   }
   // before cleaning up , we need to settle the position of the intersection points
   // on the boundary edges
+  // this needs to be collective, so we should maybe wait something
   rval = correct_intersection_points_positions();
-  ERRORR(rval, "can't correct position");
+  if (rval!=MB_SUCCESS)
+  {
+    std::cout << "can't correct position, Intx2Mesh.cpp \n";
+  }
   clean();
   return MB_SUCCESS;
 }
@@ -480,7 +484,6 @@ ErrorCode Intx2Mesh::initialize_local_kdtree(EntityHandle euler_set)
               << dep << std::endl;
   #endif
 
-    return result;
   return MB_SUCCESS;
 }
 // this will work in parallel only
@@ -1365,11 +1368,14 @@ void Intx2Mesh::correct_polygon(EntityHandle * nodes, int & nP)
     if (nodes[i]==nodes[nextIndex])
     {
       // we need to reduce nP, and collapse nodes
-      std::cout<<" nodes duplicated in list: " ;
-      for (int j=0; j<nP; j++)
-        std::cout<<nodes[j] << " " ;
-      std::cout<<"\n";
-      std::cout<<" node " << nodes[i] << " at index " << i << " is duplicated" << "\n";
+      if (dbg_1)
+      {
+        std::cout<<" nodes duplicated in list: " ;
+        for (int j=0; j<nP; j++)
+          std::cout<<nodes[j] << " " ;
+        std::cout<<"\n";
+        std::cout<<" node " << nodes[i] << " at index " << i << " is duplicated" << "\n";
+      }
       // this will work even if we start from 1 2 3 1; when i is 3, we find nextIndex is 0, then next thing does nothing
       //  (nP-1 is 3, so k is already >= nP-1); it will result in nodes -> 1, 2, 3
       for (int k=i; k<nP-1; k++)

diff --git a/tools/mbcslam/intx_mpas.cpp b/tools/mbcslam/intx_mpas.cpp
index ab50ce9..6888cb3 100644
--- a/tools/mbcslam/intx_mpas.cpp
+++ b/tools/mbcslam/intx_mpas.cpp
@@ -42,6 +42,7 @@ double gtol = 1.e-9; // this is for geometry tolerance
 double radius = 1.;// in m:  6371220.
 
 double t = 0.1, delta_t = 0.05; // check the script
+bool Verbose = false;
 
 ErrorCode manufacture_lagrange_mesh_on_sphere(Interface * mb,
     EntityHandle euler_set)
@@ -153,6 +154,11 @@ int main(int argc, char **argv)
         flux_form= true;
         index++;
       }
+      if (!strcmp(argv[index], "-v"))
+      {
+        Verbose = true;
+        index++;
+      }
 
       index++;
     }
@@ -207,17 +213,22 @@ int main(int argc, char **argv)
   rval = worker.create_departure_mesh_2nd_alg(euler_set, covering_lagr_set);
   CHECK_ERR(rval);
 
-  std::stringstream lagrIni;
-  lagrIni<<"def0" << rank<<".h5m";
-  rval = mb.write_file(lagrIni.str().c_str(), 0, 0, &covering_lagr_set, 1);
+  if (Verbose)
+  {
+    std::stringstream lagrIni;
+    lagrIni<<"def0" << rank<<".h5m";
+    rval = mb.write_file(lagrIni.str().c_str(), 0, 0, &covering_lagr_set, 1);
+  }
 
   rval = enforce_convexity(&mb, covering_lagr_set, rank);
   if (MB_SUCCESS != rval)
     return 1;
-
-  std::stringstream ste;
-  ste<<"lagr0" << rank<<".h5m";
-  rval = mb.write_file(ste.str().c_str(), 0, 0, &euler_set, 1);
+  if (Verbose)
+  {
+    std::stringstream ste;
+    ste<<"lagr0" << rank<<".h5m";
+    rval = mb.write_file(ste.str().c_str(), 0, 0, &euler_set, 1);
+  }
 
   if (MB_SUCCESS != rval)
     std::cout << "can't write lagr set\n";
@@ -230,12 +241,15 @@ int main(int argc, char **argv)
   if (MB_SUCCESS != rval)
     return 1;
 
-  std::string opts_write("");
-  std::stringstream outf;
-  outf << "intersect0" << rank << ".h5m";
-  rval = mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
-  if (MB_SUCCESS != rval)
-    std::cout << "can't write output\n";
+  if (rank<=4)
+  {
+    std::string opts_write("");
+    std::stringstream outf;
+    outf << "intersect0" << rank << ".h5m";
+    rval = mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
+    if (MB_SUCCESS != rval)
+      std::cout << "can't write output\n";
+  }
   double intx_area = area_on_sphere_lHuiller(&mb, outputSet, radius);
   double arrival_area = area_on_sphere_lHuiller(&mb, euler_set, radius);
   std::cout << " Arrival area: " << arrival_area


https://bitbucket.org/fathomteam/moab/commits/26e457149596/
Changeset:   26e457149596
Branch:      None
User:        danwu
Date:        2013-10-25 17:14:25
Summary:     Merged fathomteam/moab into master
Affected #:  21 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/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/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/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/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/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index ca86127..5b1d052 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -332,7 +332,6 @@ ErrorCode NCHelperEuler::init_mesh_vals()
   ijdimNames[0] = "__lon";
   ijdimNames[1] = "__lat";
 
-  std::stringstream ss_tag_name;
   std::string tag_name;
   Tag tagh;
 
@@ -347,7 +346,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       val[0] = lCDims[1];
       val[1] = lCDims[4];
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);
@@ -392,7 +391,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
         ERRORR(MB_FAILURE, "Unrecognized data type");
         break;
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);
@@ -414,7 +413,7 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       val[0] = gCDims[1];
       val[1] = gCDims[4];
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);

diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index a234450..7f4142e 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -336,7 +336,6 @@ ErrorCode NCHelperFV::init_mesh_vals()
   ijdimNames[2] = "__lon";
   ijdimNames[3] = "__lat";
 
-  std::stringstream ss_tag_name;
   std::string tag_name;
   Tag tagh;
 
@@ -359,7 +358,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
       val[0] = lCDims[1];
       val[1] = lCDims[4];
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);
@@ -412,7 +411,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
         ERRORR(MB_FAILURE, "Unrecognized data type");
         break;
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);
@@ -442,7 +441,7 @@ ErrorCode NCHelperFV::init_mesh_vals()
       val[0] = gCDims[1];
       val[1] = gCDims[4];
     }
-    ss_tag_name.clear();
+    std::stringstream ss_tag_name;
     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);

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 45ce16e..269312c 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) \
@@ -20,6 +24,7 @@ NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& opts,
 : UcdNCHelper(readNC, fileId, opts, fileSet)
 , maxEdgesPerCell(DEFAULT_MAX_EDGES_PER_CELL)
 , numCellGroups(0)
+, createGatherSet(false)
 {
 }
 
@@ -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;
@@ -268,10 +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;
@@ -285,396 +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;
+
+    // Allocate extra cells over procs
+    if (rank < iextra)
+      nLocalCells++;
+    start_cell_idx += std::min(rank, iextra);
 
-  // Read number of edges on each local cell
+    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");
+
+    // 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
 
   // Get local maxEdgesPerCell on this proc
-  maxEdgesPerCell = *(std::max_element(num_edges_on_local_cells.begin(), num_edges_on_local_cells.end()));
+  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;
 
-  // In parallel, do a MPI_Allreduce to get a common global maxEdgesPerCell used across all procs
+  // 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(&maxEdgesPerCell, &global_max_edges_per_cell, 1, MPI_INTEGER, MPI_MAX, myPcomm->proc_config().proc_comm());
-    assert(maxEdgesPerCell <= global_max_edges_per_cell);
+    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
 
-  // Read vertices on each local cell (connectivity)
+  // 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.");
-  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), maxEdgesPerCell};
   std::vector<int> vertices_on_local_cells(nLocalCells * maxEdgesPerCell);
-  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.");
-
-  // 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), maxEdgesPerCell};
-  std::vector<int> edges_on_local_cells(nLocalCells * maxEdgesPerCell);
-  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
+  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 and edges
-  std::set<int> local_verts_set;
-  std::set<int> local_edges_set;
-  for (int i = 0; i < nLocalCells; i++) {
-    int num_edges = num_edges_on_local_cells[i];
-    for (int j = 0; j < num_edges; j++) {
-      local_verts_set.insert(vertices_on_local_cells[i * maxEdgesPerCell + j]);
-      local_edges_set.insert(edges_on_local_cells[i * maxEdgesPerCell + j]);
-    }
+    // Increment the index for next subrange
+    indexInArray += (endh - starth + 1) * maxEdgesPerCell;
   }
-  std::copy(local_verts_set.rbegin(), local_verts_set.rend(), range_inserter(localGidVerts));
-  nLocalVertices = localGidVerts.size();
-  std::copy(local_edges_set.rbegin(), local_edges_set.rend(), range_inserter(localGidEdges));
-  nLocalEdges = localGidEdges.size();
+
+#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;
-  Range tmp_range;
-  ErrorCode 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);
-
-  // 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];
-  }
-
-  // Get ptr to gid memory for local vertices
-  Range local_verts_range(start_vertex, start_vertex + nLocalVertices - 1);
-  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 get global id tag iterator on local vertices.");
-  assert(count == nLocalVertices);
-  int* 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 file id tag iterator on local vertices.");
-    assert(count == nLocalVertices);
-    gid_data = (int*) data;
-    std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
-  }
+  ErrorCode rval = create_local_vertices(vertices_on_local_cells, start_vertex);
+  ERRORR(rval, "Failed to create local vertices 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;
-
-  // 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];
+  // 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 edges
-  rval = mbImpl->tag_iterate(mGlobalIdTag, local_edges_range.begin(), local_edges_range.end(), count, data);
-  ERRORR(rval, "Failed to get global id tag iterator on local edges.");
-  assert(count == (int) nLocalEdges);
-  gid_data = (int*) data;
-  std::copy(localGidEdges.begin(), localGidEdges.end(), gid_data);
-
-  EntityHandle start_element = 0;
+  // Create local cells, either unpadded or padded
   if (noMixedElements) {
-    // Only one group of cells (each cell is represented by a polygon with maxEdgesPerCell edges)
-    numCellGroups = 1;
-
-    // Create cells and set connectivity array with proper local vertices handles
-    EntityHandle* conn_arr_local_cells = NULL;
-    rval = _readNC->readMeshIface->get_element_connect(nLocalCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_local_cells,
-                                                      // Might have to create gather mesh later
-                                                      (create_gathers ? nLocalCells + nCells : nLocalCells));
-    ERRORR(rval, "Couldn't create local cells in MPAS mesh.");
-    Range local_cell_range(start_element, start_element + nLocalCells - 1);
-    tmp_range.insert(start_element, start_element + nLocalCells - 1);
-    faces.insert(start_element, start_element + nLocalCells - 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 global id tag iterator on local cells.");
-    assert(count == nLocalCells);
-    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];
-        conn_arr_local_cells[cell_idx * maxEdgesPerCell + i] = vert_handles[global_vert_id];
-      }
-
-      // 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;
-      }
-    }
-  } // 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.");
+  }
   else {
-    // Divide local cells into groups based on the number of edges
-    std::vector<int> local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
-    for (int i = 0; i < nLocalCells; i++) {
-      int num_edges = num_edges_on_local_cells[i];
-      local_cells_with_n_edges[num_edges].push_back(start_cell_idx + 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();
-
-    // For each non-empty cell group, create cells and set connectivity array with proper local vertices handles
-    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_cells = local_cells_with_n_edges[num_edges_per_cell].size();
-
-      rval = _readNC->readMeshIface->get_element_connect(num_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
-                                                         conn_arr_local_cells_with_n_edges[num_edges_per_cell], 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 global id tag iterator on local cells.");
-      assert(count == num_cells);
-      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);
-
-      for (int j = 0; j < num_cells; j++) {
-        int cell_idx = local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index
-        if (numCellGroups > 1)
-          cellHandleToGlobalID[start_element + j] = cell_idx;
-        cell_idx -= start_cell_idx; // Local cell index
-        for (int k = 0; k < num_edges_per_cell; k++) {
-          EntityHandle global_vert_id = vertices_on_local_cells[cell_idx * maxEdgesPerCell + k];
-          conn_arr_local_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] = vert_handles[global_vert_id];
-        }
-      }
-    } // for (int i = 0; i < numCellGroups; i++)
+    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.");
   }
 
   // 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.");
+  ERRORR(rval, "Failed to get __NUM_CELL_GROUPS tag.");
   rval = mbImpl->tag_set_data(numCellGroupsTag, &_fileSet, 1, &numCellGroups);
-  ERRORR(rval, "Trouble setting data for __NUM_CELL_GROUPS tag.");
+  ERRORR(rval, "Failed to set data for __NUM_CELL_GROUPS tag.");
 
-  // 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.");
-
-  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 vertices 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 global id tag iterator on gather vertices.");
-    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 file id tag iterator on gather 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
-    }
-
-    rval = mbImpl->add_entities(gather_set, gather_verts_range);
-    ERRORR(rval, "Couldn't add vertices to gather set.");
-
-    // 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
+    // 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");
 
-    // 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.");
-
-    // Read vertices on each gather cell (connectivity)
-    std::vector<int> vertices_on_gather_cells(nCells * maxEdgesPerCell);
-    tmp_starts_2[0] = 0;
-    tmp_starts_2[1] = 0;
-    tmp_counts_2[0] = nCells;
-    tmp_counts_2[1] = 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, 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
+    // 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.");
+    }
 
-    Range gather_cells_range;
+    // Create gather set cells, either unpadded or padded
     if (noMixedElements) {
-      // Create gather cells
-      EntityHandle* conn_arr_gather_cells;
-      // Don't need to specify allocation number here, because we know enough cells were created before
-      rval = _readNC->readMeshIface->get_element_connect(nCells, maxEdgesPerCell, MBPOLYGON, 0, start_element, conn_arr_gather_cells);
-      ERRORR(rval, "Couldn't create cells in MPAS mesh for gather set.");
-      gather_cells_range.insert(start_element, start_element + nCells - 1);
-
-      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 verts start
-          conn_arr_gather_cells[cell_idx * maxEdgesPerCell + i] = (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;
-      }
+      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 {
-      // Divide gather 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 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_cells = gather_cells_with_n_edges[num_edges_per_cell].size();
-        if (num_cells > 0) {
-          rval = _readNC->readMeshIface->get_element_connect(num_cells, num_edges_per_cell, MBPOLYGON, 0, start_element,
-                                                             conn_arr_gather_cells_with_n_edges[num_edges_per_cell], 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[num_edges_per_cell][j];
-            cell_idx--; // 1 based -> 0 based
-            for (int k = 0; k < num_edges_per_cell; k++)
-              // Connectivity array is shifted by where the gather verts start
-              conn_arr_gather_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
-                (start_vertex - 1) + vertices_on_gather_cells[cell_idx * maxEdgesPerCell + k];
-          }
-        }
-      }
+      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.");
   }
 
   return MB_SUCCESS;
@@ -773,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;
@@ -811,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++) {
@@ -874,7 +633,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
         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;
       }
@@ -894,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);
@@ -904,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;
@@ -978,7 +741,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
               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
@@ -1020,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);
@@ -1041,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);
@@ -1051,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;
@@ -1115,7 +885,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
               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
@@ -1157,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);
@@ -1177,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 2c97566..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 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 80ad2f1..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), noMixedElements(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);
@@ -218,6 +219,10 @@ ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::string
   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 eb470cd..fc75140 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -208,6 +208,7 @@ private:
   bool noVars;
   bool spectralMesh;
   bool noMixedElements;
+  bool noEdges;
   int gatherSetRank;
 
   //! Helper class instance

diff --git a/src/moab/BoundBox.hpp b/src/moab/BoundBox.hpp
index 9400944..5c51341 100644
--- a/src/moab/BoundBox.hpp
+++ b/src/moab/BoundBox.hpp
@@ -128,9 +128,9 @@ namespace moab {
     }
 
     inline std::ostream &operator<<(std::ostream& out, const BoundBox &box) {
-      out << "Min: ";
+      out << (std::string) "Min: ";
       out << box.bMin;
-      out << ", Max: ";
+      out << (std::string) ", Max: ";
       out << box.bMax;
       return out;
     }

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];

diff --git a/test/io/read_nc.cpp b/test/io/read_nc.cpp
index 0e9adf8..e57c6b3 100644
--- a/test/io/read_nc.cpp
+++ b/test/io/read_nc.cpp
@@ -88,6 +88,17 @@ void test_read_eul_all()
 
   rval = mb.tag_get_handle("COORDS", 3, MB_TYPE_DOUBLE, coordTag);
   CHECK_ERR(rval);
+
+  // Check for some tags with double underscore in the tag name
+  Tag tempTag;
+  rval = mb.tag_get_handle("__lon_LOC_MINMAX", 2, MB_TYPE_INTEGER, tempTag);
+  CHECK_ERR(rval);
+
+  rval = mb.tag_get_handle("__lon_LOC_VALS", 0, MB_TYPE_DOUBLE, tempTag, MB_TAG_VARLEN);
+  CHECK_ERR(rval);
+
+  rval = mb.tag_get_handle("__lon_GLOBAL_MINMAX", 2, MB_TYPE_INTEGER, tempTag);
+  CHECK_ERR(rval);
 }
 
 void test_read_eul_onevar() 
@@ -387,6 +398,17 @@ void test_read_fv_onetimestep()
 
   rval = mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
   CHECK_ERR(rval);
+
+  // Check for some tags with double underscore in the tag name
+  Tag tempTag;
+  rval = mb.tag_get_handle("__lon_LOC_MINMAX", 2, MB_TYPE_INTEGER, tempTag);
+  CHECK_ERR(rval);
+
+  rval = mb.tag_get_handle("__lon_LOC_VALS", 0, MB_TYPE_DOUBLE, tempTag, MB_TAG_VARLEN);
+  CHECK_ERR(rval);
+
+  rval = mb.tag_get_handle("__lon_GLOBAL_MINMAX", 2, MB_TYPE_INTEGER, tempTag);
+  CHECK_ERR(rval);
 }
 
 void test_read_fv_nomesh() 

diff --git a/test/parallel/mpastrvpart.cpp b/test/parallel/mpastrvpart.cpp
index 2b86f61..f9bfa36 100644
--- a/test/parallel/mpastrvpart.cpp
+++ b/test/parallel/mpastrvpart.cpp
@@ -13,6 +13,8 @@ static const char example[] = STRINGIFY(MESHDIR) "/io/mpasx1.642.t.2.nc";
 
 void test_read_parallel_mpas_trivial();
 void test_read_parallel_mpas_trivial_no_mixed_elements();
+void test_read_parallel_mpas_rcbzoltan();
+void test_read_parallel_mpas_rcbzoltan_no_mixed_elements();
 void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
                         int num_cells, bool test_nb_cells, bool mixed_elements);
 void test_multiple_loads_of_same_file();
@@ -27,6 +29,8 @@ int main(int argc, char* argv[])
 
   result += RUN_TEST(test_read_parallel_mpas_trivial);
   result += RUN_TEST(test_read_parallel_mpas_trivial_no_mixed_elements);
+  result += RUN_TEST(test_read_parallel_mpas_rcbzoltan);
+  result += RUN_TEST(test_read_parallel_mpas_rcbzoltan_no_mixed_elements);
   result += RUN_TEST(test_multiple_loads_of_same_file);
   result += RUN_TEST(test_multiple_loads_of_same_file_no_mixed_elements);
 
@@ -46,6 +50,18 @@ void test_read_parallel_mpas_trivial_no_mixed_elements()
   test_read_parallel(1280, true, 1920, true, 642, true, false);
 }
 
+void test_read_parallel_mpas_rcbzoltan()
+{
+  partition_method = std::string(";PARTITION_METHOD=RCBZOLTAN;PARALLEL_RESOLVE_SHARED_ENTS");
+  test_read_parallel(1280, false, 1920, false, 642, false, true);
+}
+
+void test_read_parallel_mpas_rcbzoltan_no_mixed_elements()
+{
+  partition_method = std::string(";PARTITION_METHOD=RCBZOLTAN;PARALLEL_RESOLVE_SHARED_ENTS;NO_MIXED_ELEMENTS");
+  test_read_parallel(1280, false, 1920, false, 642, false, true);
+}
+
 void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
                         int num_cells, bool test_nb_cells, bool mixed_elements)
 {

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/1ea6ca08d99f/
Changeset:   1ea6ca08d99f
Branch:      None
User:        danwu
Date:        2013-10-29 16:05:11
Summary:     Merged fathomteam/moab into master
Affected #:  3 files

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 269312c..404619d 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -377,6 +377,18 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   ERRORS(success, "Failed on wait_all.");
 #endif
 
+  // correct the connectivity array, replace the padded vertices with the last vertices in the
+  // corresponding elements; sometimes the padded vertices are 0, sometimes a big vertex id
+  // make sure they are consistent to our padded option
+  for (int i=0; i<nLocalCells; i++)
+  {
+    int nVertsInCell=num_edges_on_local_cells[i];
+    int indxInConn=i*maxEdgesPerCell;
+    for (int j=nVertsInCell; j<maxEdgesPerCell; j++)
+    {
+      vertices_on_local_cells[indxInConn+j]=vertices_on_local_cells[indxInConn+nVertsInCell-1];
+    }
+  }
   // Create local vertices
   EntityHandle start_vertex;
   ErrorCode rval = create_local_vertices(vertices_on_local_cells, start_vertex);
@@ -384,13 +396,13 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
 
   // Create local edges (unless NO_EDGES read option is set)
   if (!noEdges) {
-    rval = create_local_edges(start_vertex);
+    rval = create_local_edges(start_vertex, num_edges_on_local_cells);
     ERRORR(rval, "Failed to create local edges for MPAS mesh.");
   }
 
   // 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);
+    rval = create_padded_local_cells(vertices_on_local_cells, start_vertex, faces);
     ERRORR(rval, "Failed to create padded local cells for MPAS mesh.");
   }
   else {
@@ -960,7 +972,7 @@ ErrorCode NCHelperMPAS::redistribute_local_cells(int start_cell_idx)
     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_start = static_cast<NCDF_SIZE>(start_cell_idx-1);
     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.");
@@ -1170,7 +1182,8 @@ ErrorCode NCHelperMPAS::create_local_vertices(const std::vector<int>& vertices_o
   return MB_SUCCESS;
 }
 
-ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex)
+ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
+    const std::vector<int>& num_edges_on_local_cells)
 {
   Interface*& mbImpl = _readNC->mbImpl;
   Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
@@ -1219,6 +1232,16 @@ ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex)
   ERRORS(success, "Failed on wait_all.");
 #endif
 
+  // correct local edges in the same way as padded polygons, pad list with last edges in connectivity
+  for (int i=0; i<nLocalCells; i++)
+  {
+    int nEdgesInCell=num_edges_on_local_cells[i];
+    int indxInConn=i*maxEdgesPerCell;
+    for (int j=nEdgesInCell; j<maxEdgesPerCell; j++)
+    {
+      edges_on_local_cells[indxInConn+j]=edges_on_local_cells[indxInConn+nEdgesInCell-1];
+    }
+  }
   // 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));
@@ -1374,7 +1397,6 @@ ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_l
 }
 
 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;
@@ -1407,21 +1429,15 @@ ErrorCode NCHelperMPAS::create_padded_local_cells(const std::vector<int>& vertic
   std::copy(localGidCells.begin(), localGidCells.end(), gid_data);
 
   // Set connectivity array with proper local vertices handles
+  // vertices_on_local_cells array was already corrected to have the last vertices padded
+  // no need for extra checks considering
   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++) {
+    for (int i = 0; i < maxEdgesPerCell; 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;

diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
index 5c751a0..0f053bc 100644
--- a/src/io/NCHelperMPAS.hpp
+++ b/src/io/NCHelperMPAS.hpp
@@ -55,7 +55,7 @@ private:
   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);
+  ErrorCode create_local_edges(EntityHandle start_vertex, const std::vector<int>& num_edges_on_local_cells);
 
   //! 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,
@@ -64,7 +64,6 @@ private:
 
   //! 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

diff --git a/tools/mbzoltan/MBZoltan.cpp b/tools/mbzoltan/MBZoltan.cpp
index 6b92b4f..7590ac9 100644
--- a/tools/mbzoltan/MBZoltan.cpp
+++ b/tools/mbzoltan/MBZoltan.cpp
@@ -23,6 +23,7 @@
 #include <iostream>
 #include <assert.h>
 #include <sstream>
+#include <algorithm>
 
 #include "MBZoltan.hpp"
 #include "moab/Interface.hpp"
@@ -297,8 +298,8 @@ ErrorCode  MBZoltan::repartition(std::vector<double> & x,std::vector<double>&y,
   int retval = myZZ->Set_Param("NUM_GLOBAL_PARTITIONS", buff);
   if (ZOLTAN_OK != retval) return MB_FAILURE;
 
-    // request only partition assignments
-  retval = myZZ->Set_Param("RETURN_LISTS", "PARTITION ASSIGNMENTS");
+    // request all, import and export
+  retval = myZZ->Set_Param("RETURN_LISTS", "ALL");
   if (ZOLTAN_OK != retval) return MB_FAILURE;
 
 
@@ -314,11 +315,12 @@ ErrorCode  MBZoltan::repartition(std::vector<double> & x,std::vector<double>&y,
   int changes;
   int numGidEntries;
   int numLidEntries;
-  int dumnum1;
-  ZOLTAN_ID_PTR dum_local, dum_global;
-  int *dum1, *dum2;
-  int num_assign;
-  ZOLTAN_ID_PTR assign_gid, assign_lid;
+  int num_import;
+  ZOLTAN_ID_PTR import_global_ids, import_local_ids;
+  int * import_procs;
+  int * import_to_part;
+  int num_export;
+  ZOLTAN_ID_PTR export_global_ids, export_local_ids;
   int *assign_procs, *assign_parts;
 
   if (rank ==0)
@@ -326,8 +328,8 @@ ErrorCode  MBZoltan::repartition(std::vector<double> & x,std::vector<double>&y,
       " method for " << nprocs << " processors..." << std::endl;
 
   retval = myZZ->LB_Partition(changes, numGidEntries, numLidEntries,
-                              dumnum1, dum_global, dum_local, dum1, dum2,
-                              num_assign, assign_gid, assign_lid,
+                              num_import, import_global_ids, import_local_ids, import_procs, import_to_part,
+                              num_export, export_global_ids, export_local_ids,
                               assign_procs, assign_parts);
   if (ZOLTAN_OK != retval) return MB_FAILURE;
 
@@ -337,34 +339,15 @@ ErrorCode  MBZoltan::repartition(std::vector<double> & x,std::vector<double>&y,
     t = clock();
   }
 
+  std::sort(import_global_ids, import_global_ids+num_import, std::greater<int> ());
+  std::sort(export_global_ids, export_global_ids+num_export, std::greater<int> ());
 
-  for (size_t i=0; i<x.size(); i++)
-    sendToProcs.push_back(assign_procs[i]);
-  // free some memory after we are done
-  delete myZZ;
-  myZZ = NULL;
-  // free memory used by Zoltan
-  // form tuples for Gids!
-  TupleList gidProcs;
-
-    // allocate a TupleList of that size
-  gidProcs.initialize(1, 1, 0, 0, x.size()*2);// to account for some imbalances
-  gidProcs.enableWriteAccess();
-  for (size_t i = 0;i <sendToProcs.size(); i++)
-  {
-    gidProcs.vi_wr[i]=sendToProcs[i];
-    gidProcs.vl_wr[i]=StartID+i;
-    gidProcs.inc_n();
-  }
-
-  // now do a transfer
-  (mbpc->proc_config().crystal_router())->gs_transfer(1, gidProcs, 0);
-
-  // after this, every gidProc should contain the gids sent from other processes
-
-  int receivedGIDs=gidProcs.get_n();
-  for (int j=0;j<receivedGIDs; j++)
-    localGIDs.insert(gidProcs.vl_wr[j]);
+  Range iniGids((EntityHandle)StartID, (EntityHandle)StartID+x.size()-1);
+  Range imported, exported;
+  std::copy(import_global_ids, import_global_ids+num_import, range_inserter(imported));
+  std::copy(export_global_ids, export_global_ids+num_export, range_inserter(exported));
+  localGIDs=subtract(iniGids, exported);
+  localGIDs=unite(localGIDs, imported);
 
   return MB_SUCCESS;
 }


https://bitbucket.org/fathomteam/moab/commits/88fb42c6b1e7/
Changeset:   88fb42c6b1e7
Branch:      None
User:        danwu
Date:        2013-10-31 19:34:11
Summary:     Merged fathomteam/moab into master
Affected #:  6 files

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 5f621d7..b5e4df7 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -306,7 +306,7 @@ ErrorCode NCHelper::create_conventional_tags(const 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;;
+  std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
   Interface*& mbImpl = _readNC->mbImpl;
   DebugOutput& dbgOut = _readNC->dbgOut;
 
@@ -316,8 +316,11 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
   // Finally, read into that space
   int success;
   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
+    // This is a dummy variable, we don't have it; we created it for the dummy tag
+    // No need to read tag data for it
+    if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end())
+       continue;
+
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
       void* data = vdatas[i].varDatas[t];
 
@@ -652,7 +655,7 @@ ErrorCode NCHelper::create_attrib_string(const std::map<std::string, ReadNC::Att
   return MB_SUCCESS;
 }
 
-void NCHelper::init_dims_with_no_cvars_info()
+void NCHelper::init_dims_with_no_coord_vars_info()
 {
   std::vector<std::string>& dimNames = _readNC->dimNames;
   std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
@@ -660,24 +663,23 @@ void NCHelper::init_dims_with_no_cvars_info()
   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...
+  // Right now, candidates are from unstructured meshes, such as ncol(HOMME) and nCells(MPAS)
+  // For them, create dummy tags
+  for (unsigned int i = 0; i < dimNames.size(); i++) {
+    // If there is a variable with this dimension name, skip, we are fine; if not, create a dummy varInfo
     if (varInfo.find(dimNames[i]) != varInfo.end())
-      continue; // We already have a variable with this dimension name
+      continue;
 
     int sizeTotalVar = varInfo.size();
     std::string var_name(dimNames[i]);
-    ReadNC::VarData &data = varInfo[var_name];
+    ReadNC::VarData& data = varInfo[var_name];
     data.varName = std::string(var_name);
-    data.varId =sizeTotalVar;
+    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.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]);
@@ -686,12 +688,23 @@ 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::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
   std::vector<int>& dimLens = _readNC->dimLens;
   DebugOutput& dbgOut = _readNC->dbgOut;
 
   ErrorCode rval = MB_SUCCESS;
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // This is a dummy variable, we don't have it; we created it for the dummy tag
+    // No need to allocate tag space for it
+    if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end()) {
+      if (!vdatas[i].varTags[0]) {
+        rval = get_tag_to_set(vdatas[i], 0, vdatas[i].varTags[0]);
+        ERRORR(rval, "Trouble getting dummy tag.");
+      }
+      continue;
+    }
+
     if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim) != vdatas[i].varDims.end()))
       vdatas[i].has_t = true;
 
@@ -710,15 +723,12 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
 
       // 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)
-        {
+      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
-        {
+        else {
           vdatas[i].readStarts[t].push_back(0);
           vdatas[i].readCounts[t].push_back(tstep_nums.size());
         }
@@ -739,10 +749,12 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
           }
         }
       }
+
       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:
@@ -760,6 +772,7 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
           std::cerr << "Unrecognized data type for tag " << std::endl;
           rval = MB_FAILURE;
       }
+
       if (vdatas[i].varDims.size() <= 1)
         break;
     }
@@ -779,8 +792,7 @@ ErrorCode ScdNCHelper::check_existing_mesh() {
   /*
   // Check against parameters
   // When ghosting is used, this check might fail (to be updated later)
-  if (num_verts > 0)
-  {
+  if (num_verts > 0) {
     int expected_verts = (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) * (-1 == lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
     if (num_verts != expected_verts) {
       ERRORR(MB_FAILURE, "Number of vertices doesn't match.");
@@ -796,8 +808,7 @@ ErrorCode ScdNCHelper::check_existing_mesh() {
   /*
   // Check against parameters
   // The expected number of elements calculated below is incorrect (to be updated later)
-  if (num_elems > 0)
-  {
+  if (num_elems > 0) {
     int expected_elems = (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]) * (-1 == lDims[2] ? 1 : lDims[5] - lDims[2]);
     if (num_elems != expected_elems) {
       ERRORR(MB_FAILURE, "Number of elements doesn't match.");
@@ -990,6 +1001,7 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_nam
       vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
+
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
       if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
           && (vsetdatas[i].varDims.size() != 1)) {

diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 4982b4c..f3d1875 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -58,9 +58,9 @@ protected:
                                  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();
+  //! Initialize information for dimensions that don't have corresponding
+  //! coordinate variables - this information is used for creating dummy tags
+  void init_dims_with_no_coord_vars_info();
 
 private:
   //! Used by read_variable_to_set()

diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index 5b1d052..48056c6 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -328,17 +328,28 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       vd.entLoc = ReadNC::ENTLOCFACE;
   }
 
-  std::vector<std::string> ijdimNames(2);
-  ijdimNames[0] = "__lon";
-  ijdimNames[1] = "__lat";
+  // For Eul models, slon and slat are "virtual" dimensions (not defined in the file header)
+  std::vector<std::string> ijdimNames(4);
+  ijdimNames[0] = "__slon";
+  ijdimNames[1] = "__slat";
+  ijdimNames[2] = "__lon";
+  ijdimNames[3] = "__lat";
 
   std::string tag_name;
   Tag tagh;
 
-  // __<dim_name>_LOC_MINMAX (for lon and lat)
+  // __<dim_name>_LOC_MINMAX (for virtual slon, virtual slat, lon and lat)
   for (unsigned int i = 0; i != ijdimNames.size(); i++) {
     std::vector<int> val(2, 0);
-    if (ijdimNames[i] == "__lon") {
+    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];
     }
@@ -357,11 +368,19 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // __<dim_name>_LOC_VALS (for lon and lat)
+  // __<dim_name>_LOC_VALS (for virtual slon, virtual slat, lon and lat)
   for (unsigned int i = 0; i != ijdimNames.size(); i++) {
     void* val = NULL;
     int val_len = 0;
-    if (ijdimNames[i] == "__lon") {
+    if (ijdimNames[i] == "__slon") {
+      val = &ilVals[0];
+      val_len = ilVals.size();
+    }
+    else if (ijdimNames[i] == "__slat") {
+      val = &jlVals[0];
+      val_len = jlVals.size();
+    }
+    else if (ijdimNames[i] == "__lon") {
       val = &ilCVals[0];
       val_len = ilCVals.size();
     }
@@ -402,10 +421,18 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // __<dim_name>_GLOBAL_MINMAX (for lon and lat)
+  // __<dim_name>_GLOBAL_MINMAX (for virtual slon, virtual slat, lon and lat)
   for (unsigned int i = 0; i != ijdimNames.size(); i++) {
     std::vector<int> val(2, 0);
-    if (ijdimNames[i] == "__lon") {
+    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") {
       val[0] = gCDims[0];
       val[1] = gCDims[3];
     }
@@ -424,8 +451,8 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // Hack: create dummy tags, if needed, for variables with no corresponding variables
-  init_dims_with_no_cvars_info();
+  // Hack: create dummy tags, if needed, for dimensions with no corresponding coordinate variables
+  init_dims_with_no_coord_vars_info();
 
   return MB_SUCCESS;
 }

diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 7f4142e..253d598 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -452,8 +452,8 @@ ErrorCode NCHelperFV::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // Hack: create dummy tags, if needed, for dimensions with no corresponding variables
-  init_dims_with_no_cvars_info();
+  // Hack: create dummy tags, if needed, for dimensions with no corresponding coordinate variables
+  init_dims_with_no_coord_vars_info();
 
   return MB_SUCCESS;
 }

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index f750e78..154d61d 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -160,8 +160,8 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
       vd.entLoc = ReadNC::ENTLOCVERT;
   }
 
-  // Hack: create dummy tags, if needed, for variables with no corresponding variables
-  init_dims_with_no_cvars_info();
+  // Hack: create dummy tags for dimensions (like ncol) with no corresponding coordinate variables
+  init_dims_with_no_coord_vars_info();
 
   return MB_SUCCESS;
 }
@@ -548,6 +548,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>& var_n
       vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
+
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
       if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
           && (vsetdatas[i].varDims.size() != 1)) {

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 404619d..64c8ebf 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -135,6 +135,9 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
       vd.entLoc = ReadNC::ENTLOCFACE;
   }
 
+  // Hack: create dummy tags for dimensions (like nCells) with no corresponding coordinate variables
+  init_dims_with_no_coord_vars_info();
+
   return MB_SUCCESS;
 }
 
@@ -221,7 +224,7 @@ ErrorCode NCHelperMPAS::check_existing_mesh()
         nLocalCells = localGidCells.size();
 
         if (numCellGroups > 1) {
-          // Restore cellHandleToGlobalID
+          // Restore cellHandleToGlobalID map
           Range::const_iterator rit;
           int i;
           for (rit = local_cells.begin(), i = 0; rit != local_cells.end(); ++rit, i++)
@@ -516,6 +519,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_na
       vdatas[i].readStarts.resize(tstep_nums.size());
       vdatas[i].readCounts.resize(tstep_nums.size());
     }
+
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
       if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
           && (vsetdatas[i].varDims.size() != 1)) {
@@ -756,10 +760,11 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
               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
-                cell_idx -= localGidCells[0]; // Local cell index
+                int global_cell_idx = cellHandleToGlobalID[*(iter + j)]; // Global cell index, 1 based
+                int local_cell_idx = localGidCells.index(global_cell_idx); // Local cell index, 0 based
+                assert(local_cell_idx != -1);
                 for (int level = 0; level < vdatas[i].numLev; level++)
-                  ((double*) ptr)[j * vdatas[i].numLev + level] = tmpdoubledata[cell_idx * vdatas[i].numLev + level];
+                  ((double*) ptr)[j * vdatas[i].numLev + level] = tmpdoubledata[local_cell_idx * vdatas[i].numLev + level];
               }
 
               iter += count;
@@ -900,10 +905,11 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
               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
-                cell_idx -= localGidCells[0]; // Local cell index
+                int global_cell_idx = cellHandleToGlobalID[*(iter + j)]; // Global cell index, 1 based
+                int local_cell_idx = localGidCells.index(global_cell_idx); // Local cell index, 0 based
+                assert(local_cell_idx != -1);
                 for (int level = 0; level < vdatas[i].numLev; level++)
-                  ((double*) ptr)[j * vdatas[i].numLev + level] = tmpdoubledata[cell_idx * vdatas[i].numLev + level];
+                  ((double*) ptr)[j * vdatas[i].numLev + level] = tmpdoubledata[local_cell_idx * vdatas[i].numLev + level];
               }
 
               iter += count;
@@ -1275,9 +1281,9 @@ ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
   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.");
+  // Utilize the memory storage pointed by conn_arr_edges
   int* vertices_on_local_edges = (int*) conn_arr_edges;
 #ifdef PNETCDF_FILE
   nb_reads = localGidEdges.psize();
@@ -1315,12 +1321,12 @@ ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
 #endif
 
   // Populate connectivity for local edges
-  // Convert in-place from int to EntityHandle type (backward)
+  // Convert in-place from int to EntityHandle type (reading backward is the trick)
   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;
+    int global_vert_idx = vertices_on_local_edges[edge_vert]; // Global vertex index, 1 based
+    int local_vert_idx = localGidVerts.index(global_vert_idx); // Local vertex index, 0 based
+    assert(local_vert_idx != -1);
+    conn_arr_edges[edge_vert] = start_vertex + local_vert_idx;
   }
 
   return MB_SUCCESS;
@@ -1375,16 +1381,17 @@ ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_l
 
     // 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;
+      int global_cell_idx = (int)local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
+      int local_cell_idx = localGidCells.index(global_cell_idx); // Local cell index, 0 based
+      assert(local_cell_idx != -1);
 
-      cell_idx = localGidCells.index(cell_idx);
-      assert(cell_idx != -1);
+      if (numCellGroups > 1) {
+        // Populate cellHandleToGlobalID map to read cell variables
+        cellHandleToGlobalID[start_element + j] = global_cell_idx;
+      }
 
       for (int k = 0; k < num_edges_per_cell; k++) {
-        EntityHandle global_vert_id = vertices_on_local_cells[cell_idx * maxEdgesPerCell + k];
+        EntityHandle global_vert_id = vertices_on_local_cells[local_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] =
@@ -1431,12 +1438,12 @@ ErrorCode NCHelperMPAS::create_padded_local_cells(const std::vector<int>& vertic
   // Set connectivity array with proper local vertices handles
   // vertices_on_local_cells array was already corrected to have the last vertices padded
   // no need for extra checks considering
-  for (int cell_idx = 0; cell_idx < nLocalCells; cell_idx++) {
+  for (int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++) {
     for (int i = 0; i < maxEdgesPerCell; 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
+      EntityHandle global_vert_idx = vertices_on_local_cells[local_cell_idx * maxEdgesPerCell + i]; // Global vertex index, 1 based
+      int local_vert_idx = localGidVerts.index(global_vert_idx); // Local vertex index, 0 based
       assert(local_vert_idx != -1);
-      conn_arr_local_cells[cell_idx * maxEdgesPerCell + i] = start_vertex + local_vert_idx;
+      conn_arr_local_cells[local_cell_idx * maxEdgesPerCell + i] = start_vertex + local_vert_idx;
     }
   }
 
@@ -1650,13 +1657,13 @@ ErrorCode NCHelperMPAS::create_gather_set_cells(EntityHandle gather_set, EntityH
       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
+        int gather_cell_idx = gather_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
+        gather_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];
+            (gather_set_start_vertex - 1) + vertices_on_gather_cells[gather_cell_idx * maxEdgesPerCell + k];
       }
     }
   }
@@ -1720,16 +1727,16 @@ ErrorCode NCHelperMPAS::create_padded_gather_set_cells(EntityHandle gather_set,
   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 gather_cell_idx = 0; gather_cell_idx < nCells; gather_cell_idx++) {
+    int num_edges = num_edges_on_gather_cells[gather_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];
+      conn_arr_gather_cells[gather_cell_idx * maxEdgesPerCell + i] = (gather_set_start_vertex - 1) + vertices_on_gather_cells[gather_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];
+    EntityHandle last_vert_handle = conn_arr_gather_cells[gather_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;
+      conn_arr_gather_cells[gather_cell_idx * maxEdgesPerCell + i] = last_vert_handle;
   }
 
   return MB_SUCCESS;


https://bitbucket.org/fathomteam/moab/commits/a7330a573d42/
Changeset:   a7330a573d42
Branch:      None
User:        danwu
Date:        2013-11-07 19:58:04
Summary:     Merged fathomteam/moab into master
Affected #:  8 files

diff --git a/MeshFiles/unittest/io/mpasx1.642.t.2.nc b/MeshFiles/unittest/io/mpasx1.642.t.2.nc
index f1e8c94..f055c49 100644
Binary files a/MeshFiles/unittest/io/mpasx1.642.t.2.nc and b/MeshFiles/unittest/io/mpasx1.642.t.2.nc differ

diff --git a/src/AEntityFactory.cpp b/src/AEntityFactory.cpp
index 08ddb00..e29df97 100644
--- a/src/AEntityFactory.cpp
+++ b/src/AEntityFactory.cpp
@@ -65,7 +65,7 @@ AEntityFactory::~AEntityFactory()
   EntityType ent_type;
 
   // iterate through each element type
-  for (ent_type = MBVERTEX; ent_type != MBENTITYSET; ent_type++) {
+  for (ent_type = MBVERTEX; ent_type <= MBENTITYSET; ent_type++) {
     TypeSequenceManager::iterator i;
     TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( ent_type );
     for (i = seqman.begin(); i != seqman.end(); ++i) {

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index b5e4df7..bc8da0f 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -316,8 +316,8 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
   // Finally, read into that space
   int success;
   for (unsigned int i = 0; i < vdatas.size(); i++) {
-    // This is a dummy variable, we don't have it; we created it for the dummy tag
-    // No need to read tag data for it
+    // This is a dummy variable for a dimension with no corresponding coordinate variable
+    // No need to set its tag data
     if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end())
        continue;
 
@@ -358,21 +358,20 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
 
       if (success)
         ERRORR(MB_FAILURE, "Trouble reading variable.");
-      if (vdatas[i].varDims.size() <= 1)
-        break;
-    }
-  }
 
-  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]);
-      ErrorCode tmp_rval = convert_variable(vdatas[i], t);
-      if (MB_SUCCESS != tmp_rval)
-        rval = tmp_rval;
+      rval = convert_variable(vdatas[i], t);
+      ERRORR(rval, "Failed to convert variable.");
+
+      dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
+      rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+      ERRORR(rval, "Failed to set data for variable.");
+
       if (vdatas[i].varDims.size() <= 1)
         break;
     }
   }
+
   // Debug output, if requested
   if (1 == dbgOut.get_verbosity()) {
     dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
@@ -381,17 +380,6 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
     dbgOut.tprintf(1, "\n");
   }
 
-  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], &_fileSet, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
-      if (MB_SUCCESS != tmp_rval)
-        rval = tmp_rval;
-      if (vdatas[i].varDims.size() <= 1)
-        break;
-    }
-  }
-
   return rval;
 }
 
@@ -695,8 +683,8 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
   ErrorCode rval = MB_SUCCESS;
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
-    // This is a dummy variable, we don't have it; we created it for the dummy tag
-    // No need to allocate tag space for it
+    // This is a dummy variable for a dimension with no corresponding coordinate variable
+    // No need to allocate memory to read it
     if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end()) {
       if (!vdatas[i].varTags[0]) {
         rval = get_tag_to_set(vdatas[i], 0, vdatas[i].varTags[0]);

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 64c8ebf..6a73e31 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -380,18 +380,17 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   ERRORS(success, "Failed on wait_all.");
 #endif
 
-  // correct the connectivity array, replace the padded vertices with the last vertices in the
-  // corresponding elements; sometimes the padded vertices are 0, sometimes a big vertex id
-  // make sure they are consistent to our padded option
-  for (int i=0; i<nLocalCells; i++)
-  {
-    int nVertsInCell=num_edges_on_local_cells[i];
-    int indxInConn=i*maxEdgesPerCell;
-    for (int j=nVertsInCell; j<maxEdgesPerCell; j++)
-    {
-      vertices_on_local_cells[indxInConn+j]=vertices_on_local_cells[indxInConn+nVertsInCell-1];
-    }
+  // Correct local cell vertices array, replace the padded vertices with the last vertices
+  // in the corresponding cells; sometimes the padded vertices are 0, sometimes a large
+  // vertex id. Make sure they are consistent to our padded option
+  for (int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++) {
+    int num_edges = num_edges_on_local_cells[local_cell_idx];
+    int idx_in_local_vert_arr = local_cell_idx * maxEdgesPerCell;
+    int last_vert_idx = vertices_on_local_cells[idx_in_local_vert_arr + num_edges - 1];
+    for (int i = num_edges; i < maxEdgesPerCell; i++)
+      vertices_on_local_cells[idx_in_local_vert_arr + i] = last_vert_idx;
   }
+
   // Create local vertices
   EntityHandle start_vertex;
   ErrorCode rval = create_local_vertices(vertices_on_local_cells, start_vertex);
@@ -978,7 +977,7 @@ ErrorCode NCHelperMPAS::redistribute_local_cells(int start_cell_idx)
     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 = static_cast<NCDF_SIZE>(start_cell_idx-1);
+    NCDF_SIZE read_start = static_cast<NCDF_SIZE>(start_cell_idx - 1);
     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.");
@@ -1188,8 +1187,7 @@ ErrorCode NCHelperMPAS::create_local_vertices(const std::vector<int>& vertices_o
   return MB_SUCCESS;
 }
 
-ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
-    const std::vector<int>& num_edges_on_local_cells)
+ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex, const std::vector<int>& num_edges_on_local_cells)
 {
   Interface*& mbImpl = _readNC->mbImpl;
   Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
@@ -1238,16 +1236,16 @@ ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
   ERRORS(success, "Failed on wait_all.");
 #endif
 
-  // correct local edges in the same way as padded polygons, pad list with last edges in connectivity
-  for (int i=0; i<nLocalCells; i++)
-  {
-    int nEdgesInCell=num_edges_on_local_cells[i];
-    int indxInConn=i*maxEdgesPerCell;
-    for (int j=nEdgesInCell; j<maxEdgesPerCell; j++)
-    {
-      edges_on_local_cells[indxInConn+j]=edges_on_local_cells[indxInConn+nEdgesInCell-1];
-    }
+  // Correct local cell edges array in the same way as local cell vertices array, replace the
+  // padded edges with the last edges in the corresponding cells
+  for (int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++) {
+    int num_edges = num_edges_on_local_cells[local_cell_idx];
+    int idx_in_local_edge_arr = local_cell_idx * maxEdgesPerCell;
+    int last_edge_idx = edges_on_local_cells[idx_in_local_edge_arr + num_edges - 1];
+    for (int i = num_edges; i < maxEdgesPerCell; i++)
+      edges_on_local_cells[idx_in_local_edge_arr + i] = last_edge_idx;
   }
+
   // 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));
@@ -1320,8 +1318,9 @@ ErrorCode NCHelperMPAS::create_local_edges(EntityHandle start_vertex,
   ERRORS(success, "Failed on wait_all.");
 #endif
 
-  // Populate connectivity for local edges
-  // Convert in-place from int to EntityHandle type (reading backward is the trick)
+  // Populate connectivity data for local edges
+  // Convert in-place from int (stored in the first half) to EntityHandle
+  // Reading backward is the trick
   for (int edge_vert = nLocalEdges * 2 - 1; edge_vert >= 0; edge_vert--) {
     int global_vert_idx = vertices_on_local_edges[edge_vert]; // Global vertex index, 1 based
     int local_vert_idx = localGidVerts.index(global_vert_idx); // Local vertex index, 0 based
@@ -1341,6 +1340,7 @@ ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_l
 
   // Divide local cells into groups based on the number of edges
   Range local_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
+  // Insert larger values before smaller ones to increase efficiency
   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
@@ -1381,7 +1381,7 @@ ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_l
 
     // Set connectivity array with proper local vertices handles
     for (int j = 0; j < num_group_cells; j++) {
-      int global_cell_idx = (int)local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
+      EntityHandle global_cell_idx = local_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
       int local_cell_idx = localGidCells.index(global_cell_idx); // Local cell index, 0 based
       assert(local_cell_idx != -1);
 
@@ -1391,11 +1391,11 @@ ErrorCode NCHelperMPAS::create_local_cells(const std::vector<int>& vertices_on_l
       }
 
       for (int k = 0; k < num_edges_per_cell; k++) {
-        EntityHandle global_vert_id = vertices_on_local_cells[local_cell_idx * maxEdgesPerCell + k];
-        int idx_vertex = localGidVerts.index(global_vert_id);
-        assert(idx_vertex != -1);
+        EntityHandle global_vert_idx = vertices_on_local_cells[local_cell_idx * maxEdgesPerCell + k]; // Global vertex index, 1 based
+        int local_vert_idx = localGidVerts.index(global_vert_idx); // Local vertex index, 0 based
+        assert(local_vert_idx != -1);
         conn_arr_local_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
-            start_vertex + idx_vertex;
+            start_vertex + local_vert_idx;
       }
     }
   }
@@ -1552,40 +1552,46 @@ ErrorCode NCHelperMPAS::create_gather_set_edges(EntityHandle gather_set, EntityH
 
   // Create gather set edges
   EntityHandle start_edge;
-  EntityHandle* conn_arr_gather_edges = NULL;
+  EntityHandle* conn_arr_gather_set_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);
+  ErrorCode rval = _readNC->readMeshIface->get_element_connect(nEdges, 2, MBEDGE, 0, start_edge, conn_arr_gather_set_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);
+  Range gather_set_edges_range(start_edge, start_edge + nEdges - 1);
+  rval = mbImpl->add_entities(gather_set, gather_set_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);
+  // Utilize the memory storage pointed by conn_arr_gather_set_edges
+  int* vertices_on_gather_set_edges = (int*) conn_arr_gather_set_edges;
   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]);
+   success = NCFUNCG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges);
    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]);
+   success = NCFUNCG(_vara_int)(_fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges);
    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++)
+   // Populate connectivity data for gather set edges
+   // Convert in-place from int (stored in the first half) to EntityHandle
+   // Reading backward is the trick
+   for (int edge_vert = nEdges * 2 - 1; edge_vert >= 0; edge_vert--) {
+     int gather_set_vert_idx = vertices_on_gather_set_edges[edge_vert]; // Global vertex index, 1 based
+     gather_set_vert_idx--; // 1 based -> 0 based
      // Connectivity array is shifted by where the gather set vertices start
-     conn_arr_gather_edges[i] += gather_set_start_vertex - 1;
+     conn_arr_gather_set_edges[edge_vert] = gather_set_start_vertex + gather_set_vert_idx;
+   }
 
    return MB_SUCCESS;
 }
@@ -1598,19 +1604,19 @@ ErrorCode NCHelperMPAS::create_gather_set_cells(EntityHandle gather_set, EntityH
   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);
+  std::vector<int> num_edges_on_gather_set_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]);
+  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_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]);
+  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0]);
   ERRORS(success, "Failed to read nEdgesOnCell data.");
 #endif
 
@@ -1618,52 +1624,57 @@ ErrorCode NCHelperMPAS::create_gather_set_cells(EntityHandle gather_set, EntityH
   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);
+  std::vector<int> vertices_on_gather_set_cells(nCells * maxEdgesPerCell);
   NCDF_SIZE read_starts[2] = {0, 0};
-  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), maxEdgesPerCell};
+  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), static_cast<NCDF_SIZE>(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]);
+  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_set_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]);
+  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, &vertices_on_gather_set_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
+  Range gather_set_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
+  // Insert larger values before smaller values to increase efficiency
+  for (int i = nCells - 1; i >= 0; i--) {
+    int num_edges = num_edges_on_gather_set_cells[i];
+    gather_set_cells_with_n_edges[num_edges].insert(i + 1); // 0 based -> 1 based
   }
 
   // Create gather set cells
-  EntityHandle* conn_arr_gather_cells_with_n_edges[DEFAULT_MAX_EDGES_PER_CELL + 1];
+  EntityHandle* conn_arr_gather_set_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();
+    int num_group_cells = gather_set_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);
+                                                         conn_arr_gather_set_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);
+      Range gather_set_cells_range(start_element, start_element + num_group_cells - 1);
+      rval = mbImpl->add_entities(gather_set, gather_set_cells_range);
       ERRORR(rval, "Failed to add cells to the gather set.");
 
       for (int j = 0; j < num_group_cells; j++) {
-        int gather_cell_idx = gather_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
-        gather_cell_idx--; // 1 based -> 0 based
+        int gather_set_cell_idx = gather_set_cells_with_n_edges[num_edges_per_cell][j]; // Global cell index, 1 based
+        gather_set_cell_idx--; // 1 based -> 0 based
+
+        for (int k = 0; k < num_edges_per_cell; k++) {
+          EntityHandle gather_set_vert_idx = vertices_on_gather_set_cells[gather_set_cell_idx * maxEdgesPerCell + k]; // Global vertex index, 1 based
+          gather_set_vert_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[gather_cell_idx * maxEdgesPerCell + k];
+          conn_arr_gather_set_cells_with_n_edges[num_edges_per_cell][j * num_edges_per_cell + k] =
+            gather_set_start_vertex + gather_set_vert_idx;
+        }
       }
     }
   }
@@ -1679,64 +1690,73 @@ ErrorCode NCHelperMPAS::create_padded_gather_set_cells(EntityHandle gather_set,
   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);
+  std::vector<int> num_edges_on_gather_set_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]);
+  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_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]);
+  success = NCFUNCG(_vara_int)(_fileId, nEdgesOnCellVarId, &read_start, &read_count, &num_edges_on_gather_set_cells[0]);
   ERRORS(success, "Failed to read nEdgesOnCell data.");
 #endif
 
+  // Create gather set cells
+  EntityHandle start_element;
+  EntityHandle* conn_arr_gather_set_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_set_cells);
+  ERRORR(rval, "Failed to create cells.");
+
+  // Add cells to the gather set
+  Range gather_set_cells_range(start_element, start_element + nCells - 1);
+  rval = mbImpl->add_entities(gather_set, gather_set_cells_range);
+  ERRORR(rval, "Failed to add cells to the gather set.");
+
   // 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);
+  // Utilize the memory storage pointed by conn_arr_gather_set_cells
+  int* vertices_on_gather_set_cells = (int*) conn_arr_gather_set_cells;
   NCDF_SIZE read_starts[2] = {0, 0};
-  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), maxEdgesPerCell};
+  NCDF_SIZE read_counts[2] = {static_cast<NCDF_SIZE>(nCells), static_cast<NCDF_SIZE>(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]);
+  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells);
   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]);
+  success = NCFUNCG(_vara_int)(_fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells);
   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 gather_cell_idx = 0; gather_cell_idx < nCells; gather_cell_idx++) {
-    int num_edges = num_edges_on_gather_cells[gather_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[gather_cell_idx * maxEdgesPerCell + i] = (gather_set_start_vertex - 1) + vertices_on_gather_cells[gather_cell_idx * maxEdgesPerCell + i];
-
-    // Padding: fill connectivity array with last vertex handle
-    EntityHandle last_vert_handle = conn_arr_gather_cells[gather_cell_idx * maxEdgesPerCell + num_edges - 1];
+  // Correct gather set cell vertices array in the same way as local cell vertices array,
+  // replace the padded vertices with the last vertices in the corresponding cells
+  for (int gather_set_cell_idx = 0; gather_set_cell_idx < nCells; gather_set_cell_idx++) {
+    int num_edges = num_edges_on_gather_set_cells[gather_set_cell_idx];
+    int idx_in_gather_set_vert_arr = gather_set_cell_idx * maxEdgesPerCell;
+    int last_vert_idx = vertices_on_gather_set_cells[idx_in_gather_set_vert_arr + num_edges - 1];
     for (int i = num_edges; i < maxEdgesPerCell; i++)
-      conn_arr_gather_cells[gather_cell_idx * maxEdgesPerCell + i] = last_vert_handle;
+      vertices_on_gather_set_cells[idx_in_gather_set_vert_arr + i] = last_vert_idx;
+  }
+
+  // Populate connectivity data for gather set cells
+  // Convert in-place from int (stored in the first half) to EntityHandle
+  // Reading backward is the trick
+  for (int cell_vert = nCells * maxEdgesPerCell - 1; cell_vert >= 0; cell_vert--) {
+    int gather_set_vert_idx = vertices_on_gather_set_cells[cell_vert]; // Global vertex index, 1 based
+    gather_set_vert_idx--; // 1 based -> 0 based
+    // Connectivity array is shifted by where the gather set vertices start
+    conn_arr_gather_set_cells[cell_vert] = gather_set_start_vertex + gather_set_vert_idx;
   }
 
   return MB_SUCCESS;

diff --git a/src/parallel/ParallelComm.cpp b/src/parallel/ParallelComm.cpp
index e83653b..8efc777 100644
--- a/src/parallel/ParallelComm.cpp
+++ b/src/parallel/ParallelComm.cpp
@@ -8728,52 +8728,94 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
   }
 
   ErrorCode ParallelComm::gather_data(Range &gather_ents, Tag &tag_handle, 
-				      Tag id_tag, EntityHandle gather_set) 
+				      Tag id_tag, EntityHandle gather_set, int root_proc_rank)
   {
     int dim = mbImpl->dimension_from_handle(*gather_ents.begin());
     int bytes_per_tag = 0;
     ErrorCode rval = mbImpl->tag_get_bytes(tag_handle, bytes_per_tag);
     if (rval != MB_SUCCESS) return rval;
 
-    int sz_buffer = sizeof(int)+gather_ents.size()*(sizeof(int)+bytes_per_tag);
+    int sz_buffer = sizeof(int) + gather_ents.size()*(sizeof(int) + bytes_per_tag);
     void* senddata = malloc(sz_buffer);
     ((int*)senddata)[0] = (int) gather_ents.size();    
-    int * ptr_int = (int*)senddata+1;
+    int* ptr_int = (int*)senddata + 1;
     rval = mbImpl->tag_get_data(id_tag, gather_ents, (void*)ptr_int);
-    ptr_int = (int*)(senddata)+1+gather_ents.size();
-    rval = mbImpl->tag_get_data(tag_handle, gather_ents,(void*)ptr_int);
+    ptr_int = (int*)(senddata) + 1 + gather_ents.size();
+    rval = mbImpl->tag_get_data(tag_handle, gather_ents, (void*)ptr_int);
     std::vector<int> displs(proc_config().proc_size(), 0);
-    MPI_Gather(&sz_buffer, 1, MPI_INT, &displs[0], 1, MPI_INT, 0, comm());
+    MPI_Gather(&sz_buffer, 1, MPI_INT, &displs[0], 1, MPI_INT, root_proc_rank, comm());
     std::vector<int> recvcnts(proc_config().proc_size(), 0);
     std::copy(displs.begin(), displs.end(), recvcnts.begin());
     std::partial_sum(displs.begin(), displs.end(), displs.begin());
-    std::vector<int>::iterator lastM1 = displs.end()-1;
+    std::vector<int>::iterator lastM1 = displs.end() - 1;
     std::copy_backward(displs.begin(), lastM1, displs.end());
     //std::copy_backward(displs.begin(), --displs.end(), displs.end());
     displs[0] = 0;
 
-    if (rank()!=0)
-      MPI_Gatherv(senddata, sz_buffer, MPI_BYTE, NULL, NULL, NULL, MPI_BYTE, 0, comm());
+    if ((int)rank() != root_proc_rank)
+      MPI_Gatherv(senddata, sz_buffer, MPI_BYTE, NULL, NULL, NULL, MPI_BYTE, root_proc_rank, comm());
     else {
       Range gents;
       mbImpl->get_entities_by_dimension(gather_set, dim, gents);
       int recvbuffsz = gents.size() * (bytes_per_tag + sizeof(int)) + proc_config().proc_size() * sizeof(int);
       void* recvbuf = malloc(recvbuffsz);
-      MPI_Gatherv(senddata, sz_buffer, MPI_BYTE, recvbuf, &recvcnts[0], &displs[0], MPI_BYTE, 0, comm());
+      MPI_Gatherv(senddata, sz_buffer, MPI_BYTE, recvbuf, &recvcnts[0], &displs[0], MPI_BYTE, root_proc_rank, comm());
+
+      void* gvals = NULL;
+
+      // Test whether gents has multiple sequences
+      bool multiple_sequences = false;
+      if (gents.psize() > 1)
+        multiple_sequences = true;
+      else {
+        int count;
+        rval = mbImpl->tag_iterate(tag_handle, gents.begin(), gents.end(), count, gvals);
+        assert(NULL != gvals);
+        assert(count > 0);
+        if ((size_t)count != gents.size()) {
+          multiple_sequences = true;
+          gvals = NULL;
+        }
+      }
+
+      // If gents has multiple sequences, create a temp buffer for gathered values
+      if (multiple_sequences) {
+        gvals = malloc(gents.size() * bytes_per_tag);
+        assert(NULL != gvals);
+      }
 
-      void *gvals;
-      int count;
-      rval = mbImpl->tag_iterate(tag_handle, gents.begin(), gents.end(), count, gvals);
       for (int i = 0; i != (int)size(); ++i) {
-	int numents = *(int*)(((char*)recvbuf)+displs[i]);
-	int* id_ptr = (int*)(((char*)recvbuf)+displs[i]+sizeof(int));
-	char* val_ptr = (char*)(id_ptr+numents);
-	for (int j=0; j != numents; ++j) {
-	  int idx = id_ptr[j];
-	  memcpy((char*)gvals+(idx-1)*bytes_per_tag, val_ptr+j*bytes_per_tag, bytes_per_tag);
-	}
+        int numents = *(int*)(((char*)recvbuf) + displs[i]);
+        int* id_ptr = (int*)(((char*)recvbuf) + displs[i] + sizeof(int));
+        char* val_ptr = (char*)(id_ptr + numents);
+        for (int j = 0; j != numents; ++j) {
+          int idx = id_ptr[j];
+          memcpy((char*)gvals + (idx - 1)*bytes_per_tag, val_ptr + j*bytes_per_tag, bytes_per_tag);
+        }
+      }
+
+      // If gents has multiple sequences, copy tag data (stored in the temp buffer) to each sequence separately
+      if (multiple_sequences) {
+        Range::iterator iter = gents.begin();
+        size_t start_idx = 0;
+        while (iter != gents.end()) {
+          int count;
+          void* ptr;
+          rval = mbImpl->tag_iterate(tag_handle, iter, gents.end(), count, ptr);
+          assert(NULL != ptr);
+          assert(count > 0);
+          memcpy((char*)ptr, (char*)gvals + start_idx * bytes_per_tag, bytes_per_tag * count);
+
+          iter += count;
+          start_idx += count;
+        }
+        assert(start_idx == gents.size());
+
+        // Free the temp buffer
+        free(gvals);
       }
     }
+
     return MB_SUCCESS;
   }
 

diff --git a/src/parallel/moab/ParallelComm.hpp b/src/parallel/moab/ParallelComm.hpp
index e02d4b3..e4217ce 100644
--- a/src/parallel/moab/ParallelComm.hpp
+++ b/src/parallel/moab/ParallelComm.hpp
@@ -899,7 +899,7 @@ namespace moab {
     //! get the verbosity level of output from this pcomm
     int get_debug_verbosity();
 
-    /* \brief Gather tag value from entities down to root proc
+    /* \brief Gather tag value from entities down to a specified root proc
      * This function gathers data from a domain-decomposed mesh onto a global mesh
      * represented on the root processor.  On the root, this gather mesh is distinct from
      * the root's domain-decomposed subdomain.  Entities are matched by global id, or by
@@ -910,9 +910,10 @@ namespace moab {
      * \param tag_handle Tag whose values are being gathered
      * \param id_tag Tag to use for matching entities (global id used by default)
      * \param gather_set On root, set containing global mesh onto which to put data
+     * \param root_proc_rank Rank of the specified root processor (default rank is 0)
      */
     ErrorCode gather_data(Range &gather_ents, Tag &tag_handle, 
-			  Tag id_tag = 0, EntityHandle gather_set = 0);
+			  Tag id_tag = 0, EntityHandle gather_set = 0, int root_proc_rank = 0);
 
     /* \brief communicate extra points positions on boundary
      * This function is called after intersection of 2 meshes, to settle the

diff --git a/test/io/read_mpas_nc.cpp b/test/io/read_mpas_nc.cpp
index 597c752..d6e886f 100644
--- a/test/io/read_mpas_nc.cpp
+++ b/test/io/read_mpas_nc.cpp
@@ -1,6 +1,7 @@
 #include "TestUtil.hpp"
 #include "moab/Core.hpp"
 #include "moab/ReadUtilIface.hpp"
+#include "MBTagConventions.hpp"
 
 using namespace moab;
 
@@ -20,7 +21,9 @@ void test_read_onevar();
 void test_read_onetimestep();
 void test_read_nomesh();
 void test_read_novars();
-void test_read_no_mixed_elements();
+void test_read_no_mixed_elements(); // Test read option NO_MIXED_ELEMENTS
+void test_read_no_edges(); // Test read option NO_EDGES
+void test_gather_onevar(); // Test gather set with one variable
 
 ErrorCode get_options(std::string& opts);
 
@@ -41,8 +44,9 @@ int main(int argc, char* argv[])
   result += RUN_TEST(test_read_onetimestep);
   result += RUN_TEST(test_read_nomesh);
   result += RUN_TEST(test_read_novars);
-  // Test read option NO_MIXED_ELEMENTS
   result += RUN_TEST(test_read_no_mixed_elements);
+  result += RUN_TEST(test_read_no_edges);
+  result += RUN_TEST(test_gather_onevar);
 
 #ifdef USE_MPI
   fail = MPI_Finalize();
@@ -146,11 +150,11 @@ void test_read_all()
     // Check ke tag values on first pentagon and first hexagon
     EntityHandle cell_ents[] = {cells[0], cells[12]};
     rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(1.5, val[0], eps);
-    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    CHECK_REAL_EQUAL(15.001, val[0], eps);
+    CHECK_REAL_EQUAL(16.013, val[1], eps);
     rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(2.5, val[0], eps);
-    CHECK_REAL_EQUAL(2.6, val[1], eps);
+    CHECK_REAL_EQUAL(25.001, val[0], eps);
+    CHECK_REAL_EQUAL(26.013, val[1], eps);
   }
 }
 
@@ -163,8 +167,6 @@ void test_read_onevar()
   CHECK_ERR(rval);
 
   opts += std::string(";VARIABLE=ke");
-  // Create gather set
-  opts += std::string(";GATHER_SET=");
   rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
@@ -187,38 +189,15 @@ void test_read_onevar()
     Range cells;
     rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
     assert(rval == MB_SUCCESS);
-    CHECK_EQUAL((size_t)1284, cells.size()); // Gather set cells included
-#ifdef USE_MPI
-    // If MOAB is compiled parallel, sequence size requested are increased
-    // by a factor of 1.5, to allow for ghosts. This will introduce a gap
-    // between the two face sequences.
-    CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
-#else
-    CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
-#endif
-
-    // Get gather set
-    EntityHandle gather_set;
-    ReadUtilIface* readUtilIface;
-    mb.query_interface(readUtilIface);
-    rval = readUtilIface->get_gather_set(gather_set);
-    CHECK_ERR(rval);
-
-    // Get gather set entities
-    Range gather_ents;
-    rval = mb.get_entities_by_handle(gather_set, gather_ents);
-    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)642, cells.size());
 
-    // Remove gather set cells
-    cells = subtract(cells, gather_ents);
-    CHECK_EQUAL((size_t)642, cells.size()); // Gather set cells excluded
 #ifdef USE_MPI
     // If MOAB is compiled parallel, sequence size requested are increased
     // by a factor of 1.5, to allow for ghosts. This will introduce a gap
     // between the two face sequences.
-    CHECK_EQUAL((size_t)2, cells.psize()); // Gather set cells excluded
+    CHECK_EQUAL((size_t)2, cells.psize());
 #else
-    CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded
+    CHECK_EQUAL((size_t)1, cells.psize());
 #endif
 
     // Check ke tag values on first pentagon and first hexagon
@@ -226,11 +205,11 @@ void test_read_onevar()
     double val[2];
     EntityHandle cell_ents[] = {cells[0], cells[12]};
     rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(1.5, val[0], eps);
-    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    CHECK_REAL_EQUAL(15.001, val[0], eps);
+    CHECK_REAL_EQUAL(16.013, val[1], eps);
     rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(2.5, val[0], eps);
-    CHECK_REAL_EQUAL(2.6, val[1], eps);
+    CHECK_REAL_EQUAL(25.001, val[0], eps);
+    CHECK_REAL_EQUAL(26.013, val[1], eps);
   }
 }
 
@@ -368,7 +347,8 @@ void test_read_no_mixed_elements()
     rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
     assert(rval == MB_SUCCESS);
     CHECK_EQUAL((size_t)642, cells.size());
-    // Only one group of cells (each cell is actually represented by a 10-vertex polygon)
+    // Only one group of cells (pentagons are padded to hexagons,
+    // e.g. connectivity [1 2 3 4 5] => [1 2 3 4 5 5])
     CHECK_EQUAL((size_t)1, cells.psize());
 
     const double eps = 1e-20;
@@ -377,15 +357,112 @@ void test_read_no_mixed_elements()
     // Check ke tag values on first pentagon and first hexagon
     EntityHandle cell_ents[] = {cells[0], cells[12]};
     rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(1.5, val[0], eps);
-    CHECK_REAL_EQUAL(1.6, val[1], eps);
+    CHECK_REAL_EQUAL(15.001, val[0], eps);
+    CHECK_REAL_EQUAL(16.013, val[1], eps);
     rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(2.5, val[0], eps);
-    CHECK_REAL_EQUAL(2.6, val[1], eps);
+    CHECK_REAL_EQUAL(25.001, val[0], eps);
+    CHECK_REAL_EQUAL(26.013, val[1], eps);
+  }
+}
+
+void test_read_no_edges()
+{
+  Core moab;
+  Interface& mb = moab;
+  std::string opts;
+  ErrorCode rval = get_options(opts);
+  CHECK_ERR(rval);
+
+  opts += std::string(";NO_EDGES;VARIABLE=");
+  rval = mb.load_file(example, NULL, opts.c_str());
+  CHECK_ERR(rval);
+
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  procs = pcomm->proc_config().proc_size();
+#endif
+
+  // Make check runs this test in one processor
+  if (1 == procs) {
+    // Get edges
+    Range edges;
+    rval = mb.get_entities_by_type(0, MBEDGE, edges);
+    assert(rval == MB_SUCCESS);
+    CHECK_EQUAL((size_t)0, edges.size());
   }
 }
 
-ErrorCode get_options(std::string &opts) 
+void test_gather_onevar()
+{
+  Core moab;
+  Interface& mb = moab;
+  std::string opts;
+  ErrorCode rval = get_options(opts);
+  CHECK_ERR(rval);
+
+  EntityHandle file_set;
+  rval = mb.create_meshset(MESHSET_SET, file_set);
+  CHECK_ERR(rval);
+
+  // Get cell variable ke
+  opts += std::string(";VARIABLE=ke;");
+  // Create gather set
+  opts += std::string(";GATHER_SET=0;");
+  rval = mb.load_file(example, &file_set, opts.c_str());
+  CHECK_ERR(rval);
+
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  int procs = pcomm->proc_config().proc_size();
+
+  // Make check runs this test in one processor
+  if (1 == procs) {
+    Range cells, cells_owned;
+    rval = mb.get_entities_by_type(file_set, MBPOLYGON, cells);
+    CHECK_ERR(rval);
+
+    // Get locally owned cells
+    rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &cells_owned);
+    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)642, cells_owned.size());
+    CHECK_EQUAL((size_t)2, cells_owned.psize());
+
+    // Get gather set
+    EntityHandle gather_set;
+    ReadUtilIface* readUtilIface;
+    mb.query_interface(readUtilIface);
+    rval = readUtilIface->get_gather_set(gather_set);
+    CHECK_ERR(rval);
+
+    Tag ke_tag0, gid_tag;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0, MB_TAG_DENSE);
+    CHECK_ERR(rval);
+
+    rval = mb.tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_DENSE);
+    CHECK_ERR(rval);
+
+    pcomm->gather_data(cells_owned, ke_tag0, gid_tag, gather_set);
+
+    // Get gather set cells
+    Range gather_set_cells;
+    rval = mb.get_entities_by_type(gather_set, MBPOLYGON, gather_set_cells);
+    CHECK_EQUAL((size_t)642, gather_set_cells.size());
+    CHECK_EQUAL((size_t)2, gather_set_cells.psize());
+
+    const double eps = 1e-20;
+    double val[2];
+
+    // Check ke0 tag values on first pentagon and first hexagon of the gather set cells
+    EntityHandle cell_ents[] = {gather_set_cells[0], gather_set_cells[12]};
+    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+    CHECK_REAL_EQUAL(15.001, val[0], eps);
+    CHECK_REAL_EQUAL(16.013, val[1], eps);
+  }
+#endif
+}
+
+ErrorCode get_options(std::string& opts)
 {
 #ifdef USE_MPI
   // Use parallel options

diff --git a/test/parallel/mpastrvpart.cpp b/test/parallel/mpastrvpart.cpp
index f9bfa36..24f0b9b 100644
--- a/test/parallel/mpastrvpart.cpp
+++ b/test/parallel/mpastrvpart.cpp
@@ -325,8 +325,8 @@ void test_multiple_loads_of_same_file()
       // Check ke0 tag values on first pentagon and first hexagon
       EntityHandle cell_ents[] = {cells[0], cells[12]};
       rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-      CHECK_REAL_EQUAL(1.5, val[0], eps);
-      CHECK_REAL_EQUAL(1.6, val[1], eps);
+      CHECK_REAL_EQUAL(15.001, val[0], eps);
+      CHECK_REAL_EQUAL(16.013, val[1], eps);
     }
     else if (1 == rank) {
       CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included
@@ -431,8 +431,8 @@ void test_multiple_loads_of_same_file_no_mixed_elements()
       // Check ke0 tag values on first pentagon and first hexagon
       EntityHandle cell_ents[] = {cells[0], cells[12]};
       rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-      CHECK_REAL_EQUAL(1.5, val[0], eps);
-      CHECK_REAL_EQUAL(1.6, val[1], eps);
+      CHECK_REAL_EQUAL(15.001, val[0], eps);
+      CHECK_REAL_EQUAL(16.013, val[1], eps);
     }
     else if (1 == rank) {
       CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included


https://bitbucket.org/fathomteam/moab/commits/f418deb2b578/
Changeset:   f418deb2b578
Branch:      None
User:        danwu
Date:        2013-11-08 18:25:29
Summary:     Merged fathomteam/moab into master
Affected #:  6 files

diff --git a/configure.ac b/configure.ac
index 937385d..bdc225b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -698,7 +698,7 @@ if test "xyes" = "x$WITH_ZOLTAN"; then
                   [#include <stdlib.h>])
   CPPFLAGS="$old_CPPFLAGS"
   AC_LANG_POP([C++])
-  
+
     # Build LDFLAGS for Zoltan
   found=no
   if test "x" != "x$ZOLTAN_DIR"; then
@@ -720,7 +720,7 @@ if test "xyes" = "x$WITH_ZOLTAN"; then
       ZOLTAN_LIB_FLAGS="$ZOLTAN_LIB_FLAGS -L$ZOLTAN_DIR"
     fi
   fi
-  
+
     # Test for Zoltan library, possibly requiring parmetis
   old_LDFLAGS="$LDFLAGS"
   LDFLAGS="$LDFLAGS $ZOLTAN_LIB_FLAGS"
@@ -731,7 +731,9 @@ if test "xyes" = "x$WITH_ZOLTAN"; then
                   [AC_MSG_ERROR([zoltan library not found or not usable.  Perhaps you need to specify --with-parmetis=@<:@DIR@:>@?])],
                   [-lparmetis -lmetis])])
   LDFLAGS="$old_LDFLAGS"
-  
+
+    # Define macro HAVE_ZOLTAN
+  AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_ZOLTAN"  
 fi
 
 AC_SUBST(ZOLTAN_LIBS)

diff --git a/src/Makefile.am b/src/Makefile.am
index 3a86984..64b8a0f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,6 @@ AM_CPPFLAGS += -DIS_BUILDING_MB \
 # The directory in which to install headers
 libMOAB_la_includedir = $(includedir)
 
-
 # The list of source files, and any header files that do not need to be installed
 libMOAB_la_SOURCES = \
   AdaptiveKDTree.cpp \
@@ -205,23 +204,24 @@ 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
+  AM_CPPFLAGS += $(ZOLTAN_INC_FLAGS)
   # 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
 
-
 MOAB_FCDefs.h: FCDefs.h
 	$(AM_V_GEN)cd .. && ./config.status src/MOAB_FCDefs.h
 

diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index 968f47f..60caa48 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -40,8 +40,9 @@ endif
 endif
 
 if ENABLE_mbzoltan
-  AM_CPPFLAGS += -DHAVE_ZOLTAN -I$(srcdir)/../../tools/mbzoltan $(ZOLTAN_INC_FLAGS) 
+  AM_CPPFLAGS += -I$(srcdir)/../../tools/mbzoltan $(ZOLTAN_INC_FLAGS) 
 endif
+
 if HDF5_FILE
   libmoabio_la_LIBADD += mhdf/libmhdf.la
   MOAB_HDF5_SRCS = HDF5Common.cpp \
@@ -58,6 +59,7 @@ if HDF5_FILE
 else
   MOAB_HDF5_SRCS = 
 endif
+
 if CCMIO_FILE
   MOAB_CCMIO_SRCS = WriteCCMIO.cpp WriteCCMIO.hpp ReadCCMIO.cpp ReadCCMIO.hpp
   libmoabio_la_LIBADD += $(CCMIO_LIBS)
@@ -142,7 +144,5 @@ libmoabio_la_SOURCES = \
   $(MOAB_DAMSEL_SRCS) \
   $(MOAB_CGM_SRCS)
 
-
 libmoabio_la_includedir = $(includedir)
 nobase_libmoabio_la_include_HEADERS = moab/ExoIIInterface.hpp
-

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 6a73e31..54ba598 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -4,7 +4,7 @@
 #include "moab/SpectralMeshTool.hpp"
 #include "MBTagConventions.hpp"
 
-#if HAVE_ZOLTAN
+#ifdef HAVE_ZOLTAN
 #include "MBZoltan.hpp"
 #endif
 
@@ -971,7 +971,7 @@ 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)
+#if defined(USE_MPI) && defined(HAVE_ZOLTAN)
     // Read x coordinates of cell centers
     int xCellVarId;
     int success = NCFUNC(inq_varid)(_fileId, "xCell", &xCellVarId);

diff --git a/test/parallel/Makefile.am b/test/parallel/Makefile.am
index d611c7b..6dd3207 100644
--- a/test/parallel/Makefile.am
+++ b/test/parallel/Makefile.am
@@ -11,14 +11,13 @@ AM_CPPFLAGS += -DIS_BUILDING_MB \
                -I$(top_srcdir)/src \
                -I$(top_srcdir)/src/parallel \
                -I$(top_srcdir)/src/io/mhdf/include
-               
+
 if ENABLE_mbcoupler
   AM_CPPFLAGS += -I$(top_srcdir)/tools/mbcoupler \
                  -I$(top_srcdir)/itaps \
                  -I$(top_srcdir)/itaps/imesh \
                  -I$(top_builddir)/itaps/imesh \
-                 -I$(top_srcdir)/src/moab/point_locater/lotte 
-  
+                 -I$(top_srcdir)/src/moab/point_locater/lotte
 endif
 
 if ENABLE_mbcslam

diff --git a/test/parallel/mpastrvpart.cpp b/test/parallel/mpastrvpart.cpp
index 24f0b9b..b42f11e 100644
--- a/test/parallel/mpastrvpart.cpp
+++ b/test/parallel/mpastrvpart.cpp
@@ -4,6 +4,9 @@
 #include "moab/ProgOptions.hpp"
 #include "MBParallelConventions.h"
 #include "moab/ReadUtilIface.hpp"
+#include "MBTagConventions.hpp"
+
+#include <sstream>
 
 using namespace moab;
 
@@ -11,26 +14,57 @@ using namespace moab;
 static const char example[] = STRINGIFY(MESHDIR) "/io/mpasx1.642.t.2.nc";
 #endif
 
-void test_read_parallel_mpas_trivial();
-void test_read_parallel_mpas_trivial_no_mixed_elements();
-void test_read_parallel_mpas_rcbzoltan();
-void test_read_parallel_mpas_rcbzoltan_no_mixed_elements();
-void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
-                        int num_cells, bool test_nb_cells, bool mixed_elements);
+void test_read_onevar_trivial();
+void test_read_onevar_trivial_no_mixed_elements();
+#if defined(USE_MPI) && defined(HAVE_ZOLTAN)
+void test_read_onevar_rcbzoltan();
+void test_read_onevar_rcbzoltan_no_mixed_elements();
+#endif
+
+void test_read_mesh_parallel_trivial();
+void test_read_mesh_parallel_trivial_no_mixed_elements();
+#if defined(USE_MPI) && defined(HAVE_ZOLTAN)
+void test_read_mesh_parallel_rcbzoltan();
+void test_read_mesh_parallel_rcbzoltan_no_mixed_elements();
+#endif
+
+void test_gather_onevar_on_rank0();
+void test_gather_onevar_on_rank1();
+
 void test_multiple_loads_of_same_file();
 void test_multiple_loads_of_same_file_no_mixed_elements();
 
-std::string partition_method;
+// Helper functions
+void read_one_cell_var(bool rcbzoltan, bool no_mixed_elements);
+void read_mesh_parallel(bool rcbzoltan, bool no_mixed_elements);
+void gather_one_cell_var(int gather_set_rank);
+void multiple_loads_of_same_file(bool no_mixed_elements);
+
+std::string read_options;
+const double eps = 1e-20;
 
 int main(int argc, char* argv[])
 {
   MPI_Init(&argc, &argv);
   int result = 0;
 
-  result += RUN_TEST(test_read_parallel_mpas_trivial);
-  result += RUN_TEST(test_read_parallel_mpas_trivial_no_mixed_elements);
-  result += RUN_TEST(test_read_parallel_mpas_rcbzoltan);
-  result += RUN_TEST(test_read_parallel_mpas_rcbzoltan_no_mixed_elements);
+  result += RUN_TEST(test_read_onevar_trivial);
+  result += RUN_TEST(test_read_onevar_trivial_no_mixed_elements);
+#if defined(USE_MPI) && defined(HAVE_ZOLTAN)
+  result += RUN_TEST(test_read_onevar_rcbzoltan);
+  result += RUN_TEST(test_read_onevar_rcbzoltan_no_mixed_elements);
+#endif
+
+  result += RUN_TEST(test_read_mesh_parallel_trivial);
+  result += RUN_TEST(test_read_mesh_parallel_trivial_no_mixed_elements);
+#if defined(USE_MPI) && defined(HAVE_ZOLTAN)
+  result += RUN_TEST(test_read_mesh_parallel_rcbzoltan);
+  result += RUN_TEST(test_read_mesh_parallel_rcbzoltan_no_mixed_elements);
+#endif
+
+  result += RUN_TEST(test_gather_onevar_on_rank0);
+  result += RUN_TEST(test_gather_onevar_on_rank1);
+
   result += RUN_TEST(test_multiple_loads_of_same_file);
   result += RUN_TEST(test_multiple_loads_of_same_file_no_mixed_elements);
 
@@ -38,436 +72,553 @@ int main(int argc, char* argv[])
   return result;
 }
 
-void test_read_parallel_mpas_trivial()
+void test_read_onevar_trivial()
+{
+  read_one_cell_var(false, false);
+}
+
+void test_read_onevar_trivial_no_mixed_elements()
+{
+  read_one_cell_var(false, true);
+}
+
+void test_read_onevar_rcbzoltan()
+{
+  read_one_cell_var(true, false);
+}
+
+void test_read_onevar_rcbzoltan_no_mixed_elements()
 {
-  partition_method = std::string(";PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS");
-  test_read_parallel(1280, true, 1920, true, 642, true, true);
+  read_one_cell_var(true, true);
 }
 
-void test_read_parallel_mpas_trivial_no_mixed_elements()
+void test_read_mesh_parallel_trivial()
 {
-  partition_method = std::string(";PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS;NO_MIXED_ELEMENTS");
-  test_read_parallel(1280, true, 1920, true, 642, true, false);
+  read_mesh_parallel(false, false);
 }
 
-void test_read_parallel_mpas_rcbzoltan()
+void test_read_mesh_parallel_trivial_no_mixed_elements()
 {
-  partition_method = std::string(";PARTITION_METHOD=RCBZOLTAN;PARALLEL_RESOLVE_SHARED_ENTS");
-  test_read_parallel(1280, false, 1920, false, 642, false, true);
+  read_mesh_parallel(false, true);
 }
 
-void test_read_parallel_mpas_rcbzoltan_no_mixed_elements()
+void test_read_mesh_parallel_rcbzoltan()
 {
-  partition_method = std::string(";PARTITION_METHOD=RCBZOLTAN;PARALLEL_RESOLVE_SHARED_ENTS;NO_MIXED_ELEMENTS");
-  test_read_parallel(1280, false, 1920, false, 642, false, true);
+  read_mesh_parallel(true, false);
 }
 
-void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, bool test_nb_edges,
-                        int num_cells, bool test_nb_cells, bool mixed_elements)
+void test_read_mesh_parallel_rcbzoltan_no_mixed_elements()
+{
+  read_mesh_parallel(true, true);
+}
+
+void test_gather_onevar_on_rank0()
+{
+  gather_one_cell_var(0);
+}
+
+void test_gather_onevar_on_rank1()
+{
+  gather_one_cell_var(1);
+}
+
+void test_multiple_loads_of_same_file()
+{
+  multiple_loads_of_same_file(false);
+}
+
+void test_multiple_loads_of_same_file_no_mixed_elements()
+{
+  multiple_loads_of_same_file(true);
+}
+
+// Helper functions
+void read_one_cell_var(bool rcbzoltan, bool no_mixed_elements)
 {
   Core moab;
   Interface& mb = moab;
-  EntityHandle file_set;
-  ErrorCode rval;
-  rval = mb.create_meshset(MESHSET_SET, file_set);
+
+  read_options = "PARALLEL=READ_PART;PARTITION_METHOD=TRIVIAL;NO_EDGES;VARIABLE=ke";
+  if (rcbzoltan)
+    read_options = "PARALLEL=READ_PART;PARTITION_METHOD=RCBZOLTAN;NO_EDGES;VARIABLE=ke";
+
+  if (no_mixed_elements)
+    read_options += ";NO_MIXED_ELEMENTS";
+
+  ErrorCode rval = mb.load_file(example, NULL, read_options.c_str());
+  CHECK_ERR(rval);
+
+  // Get local edges
+  Range local_edges;
+  rval = mb.get_entities_by_type(0, MBEDGE, local_edges);
+  CHECK_ERR(rval);
+  CHECK_EQUAL((size_t)0, local_edges.size());
+
+  // Get local cells
+  Range local_cells;
+  rval = mb.get_entities_by_type(0, MBPOLYGON, local_cells);
   CHECK_ERR(rval);
 
-  std::string opt = std::string("PARALLEL=READ_PART") + partition_method;
-  // Create gather set in processor 0
-  opt += std::string(";GATHER_SET=0");
-  rval = mb.load_file(example, &file_set, opt.c_str());
+  Tag gid_tag;
+  rval = mb.tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_DENSE);
   CHECK_ERR(rval);
 
+  std::vector<int> gids(local_cells.size());
+  rval = mb.tag_get_data(gid_tag, local_cells, &gids[0]);
+  Range local_cell_gids;
+  std::copy(gids.rbegin(), gids.rend(), range_inserter(local_cell_gids));
+
   ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
   int procs = pcomm->proc_config().proc_size();
   int rank = pcomm->proc_config().proc_rank();
 
-  rval = pcomm->check_all_shared_handles();
-  CHECK_ERR(rval);
+  // Make check runs this test on two processors
+  if (2 == procs) {
+    CHECK_EQUAL((size_t)321, local_cells.size());
+    CHECK_EQUAL((size_t)321, local_cell_gids.size());
 
-  // Get the total # owned verts
-  Range verts;
-  rval = mb.get_entities_by_type(0, MBVERTEX, verts);
-  CHECK_ERR(rval);
+    // Check tag for cell variable ke at timestep 0
+    Tag ke_tag0;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+    CHECK_ERR(rval);
+
+    // Check tag for cell variable ke at timestep 1
+    Tag ke_tag1;
+    rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+    CHECK_ERR(rval);
+
+    // Get ke0 and ke1 tag values on 3 local cells
+    EntityHandle cell_ents[] = {local_cells[0], local_cells[160], local_cells[320]};
+    double ke0_val[3];
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 3, ke0_val);
+    CHECK_ERR(rval);
+    double ke1_val[3];
+    rval = mb.tag_get_data(ke_tag1, cell_ents, 3, ke1_val);
+    CHECK_ERR(rval);
 
-  int my_verts_num = verts.size();
-  if (test_nb_nodes && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(2400, my_verts_num); // Gather set vertices included
-    else if (1 == rank)
-      CHECK_EQUAL(1122, my_verts_num); // Not owned vertices included
+    if (rcbzoltan) {
+      if (no_mixed_elements)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+      else
+        CHECK_EQUAL((size_t)2, local_cells.psize());
+
+      CHECK_EQUAL((size_t)37, local_cell_gids.psize());
+
+      if (0 == rank) {
+        CHECK_EQUAL(1, (int)local_cell_gids[0]);
+        CHECK_EQUAL(284, (int)local_cell_gids[160]);
+        CHECK_EQUAL(630, (int)local_cell_gids[320]);
+
+        CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+        CHECK_REAL_EQUAL(16.284, ke0_val[1], eps);
+        CHECK_REAL_EQUAL(16.630, ke0_val[2], eps);
+        CHECK_REAL_EQUAL(25.001, ke1_val[0], eps);
+        CHECK_REAL_EQUAL(26.284, ke1_val[1], eps);
+        CHECK_REAL_EQUAL(26.630, ke1_val[2], eps);
+      }
+      else if (1 == rank) {
+        CHECK_EQUAL(4, (int)local_cell_gids[0]);
+        CHECK_EQUAL(341, (int)local_cell_gids[160]);
+        CHECK_EQUAL(642, (int)local_cell_gids[320]);
+
+        CHECK_REAL_EQUAL(15.004, ke0_val[0], eps);
+        CHECK_REAL_EQUAL(16.341, ke0_val[1], eps);
+        CHECK_REAL_EQUAL(16.642, ke0_val[2], eps);
+        CHECK_REAL_EQUAL(25.004, ke1_val[0], eps);
+        CHECK_REAL_EQUAL(26.341, ke1_val[1], eps);
+        CHECK_REAL_EQUAL(26.642, ke1_val[2], eps);
+      }
+    }
+    else {
+      CHECK_EQUAL((size_t)1, local_cell_gids.psize());
+
+      if (0 == rank) {
+        if (no_mixed_elements)
+          CHECK_EQUAL((size_t)1, local_cells.psize());
+        else
+          CHECK_EQUAL((size_t)2, local_cells.psize());
+        CHECK_EQUAL(1, (int)local_cell_gids[0]);
+        CHECK_EQUAL(161, (int)local_cell_gids[160]);
+        CHECK_EQUAL(321, (int)local_cell_gids[320]);
+
+        CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+        CHECK_REAL_EQUAL(16.161, ke0_val[1], eps);
+        CHECK_REAL_EQUAL(16.321, ke0_val[2], eps);
+        CHECK_REAL_EQUAL(25.001, ke1_val[0], eps);
+        CHECK_REAL_EQUAL(26.161, ke1_val[1], eps);
+        CHECK_REAL_EQUAL(26.321, ke1_val[2], eps);
+      }
+      else if (1 == rank) {
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+        CHECK_EQUAL(322, (int)local_cell_gids[0]);
+        CHECK_EQUAL(482, (int)local_cell_gids[160]);
+        CHECK_EQUAL(642, (int)local_cell_gids[320]);
+
+        CHECK_REAL_EQUAL(16.322, ke0_val[0], eps);
+        CHECK_REAL_EQUAL(16.482, ke0_val[1], eps);
+        CHECK_REAL_EQUAL(16.642, ke0_val[2], eps);
+        CHECK_REAL_EQUAL(26.322, ke1_val[0], eps);
+        CHECK_REAL_EQUAL(26.482, ke1_val[1], eps);
+        CHECK_REAL_EQUAL(26.642, ke1_val[2], eps);
+      }
+    }
   }
+}
 
-  rval = pcomm->filter_pstatus(verts, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+void read_mesh_parallel(bool rcbzoltan, bool no_mixed_elements)
+{
+  Core moab;
+  Interface& mb = moab;
+
+  read_options = "PARALLEL=READ_PART;PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS;VARIABLE=";
+  if (rcbzoltan)
+    read_options = "PARALLEL=READ_PART;PARTITION_METHOD=RCBZOLTAN;PARALLEL_RESOLVE_SHARED_ENTS;VARIABLE=";
+
+  if (no_mixed_elements)
+    read_options += ";NO_MIXED_ELEMENTS";
+
+  ErrorCode rval = mb.load_file(example, NULL, read_options.c_str());
   CHECK_ERR(rval);
 
-  my_verts_num = verts.size();
-  if (test_nb_nodes && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(2400, my_verts_num); // Gather set vertices included
-    else if (1 == rank)
-      CHECK_EQUAL(160, my_verts_num); // Not owned vertices excluded
-  }
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  int procs = pcomm->proc_config().proc_size();
+  int rank = pcomm->proc_config().proc_rank();
 
-  // Get the total # owned edges
-  Range edges;
-  rval = mb.get_entities_by_type(0, MBEDGE, edges);
+  rval = pcomm->check_all_shared_handles();
   CHECK_ERR(rval);
 
-  int my_edges_num = edges.size();
-  if (test_nb_edges && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(3358, my_edges_num); // Gather set edges included
-    else if (1 == rank)
-      CHECK_EQUAL(1444, my_edges_num); // Not owned edges included
+  // Get local vertices
+  Range local_verts;
+  rval = mb.get_entities_by_type(0, MBVERTEX, local_verts);
+  CHECK_ERR(rval);
+
+  int verts_num = local_verts.size();
+  if (2 == procs) {
+    if (rcbzoltan) {
+      if (0 == rank)
+        CHECK_EQUAL(685, verts_num);
+      else if (1 == rank)
+        CHECK_EQUAL(685, verts_num); // Not owned vertices included
+    }
+    else {
+      if (0 == rank)
+        CHECK_EQUAL(1120, verts_num);
+      else if (1 == rank)
+        CHECK_EQUAL(1122, verts_num); // Not owned vertices included
+    }
   }
 
-  rval = pcomm->filter_pstatus(edges, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+  rval = pcomm->filter_pstatus(local_verts, PSTATUS_NOT_OWNED, PSTATUS_NOT);
   CHECK_ERR(rval);
 
-  my_edges_num = edges.size();
-  if (test_nb_edges && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(3358, my_edges_num); // Gather set edges included
-    else if (1 == rank)
-      CHECK_EQUAL(482, my_edges_num); // Not owned edges excluded
+  verts_num = local_verts.size();
+  if (2 == procs) {
+    if (rcbzoltan) {
+      if (0 == rank)
+        CHECK_EQUAL(685, verts_num);
+      else if (1 == rank)
+        CHECK_EQUAL(595, verts_num); // Not owned vertices excluded
+    }
+    else {
+      if (0 == rank)
+        CHECK_EQUAL(1120, verts_num);
+      else if (1 == rank)
+        CHECK_EQUAL(160, verts_num); // Not owned vertices excluded
+    }
   }
 
-  // Get the total # owned cells
-  Range cells;
-  rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+  // Get local edges
+  Range local_edges;
+  rval = mb.get_entities_by_type(0, MBEDGE, local_edges);
   CHECK_ERR(rval);
 
-  int my_cells_num = cells.size();
-  if (test_nb_cells && 2 == procs) {
-    if (0 == rank) {
-      CHECK_EQUAL(963, my_cells_num); // Gather set cells included
-      if (mixed_elements)
-        CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
-      else
-        CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
+  int edges_num = local_edges.size();
+  if (2 == procs) {
+    if (rcbzoltan) {
+      if (0 == rank)
+        CHECK_EQUAL(1005, edges_num);
+      else if (1 == rank)
+        CHECK_EQUAL(1005, edges_num); // Not owned edges included
     }
-    else if (1 == rank) {
-      CHECK_EQUAL(321, my_cells_num); // Not owned cells included
-      CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells included
+    else {
+      if (0 == rank)
+        CHECK_EQUAL(1438, edges_num);
+      else if (1 == rank)
+        CHECK_EQUAL(1444, edges_num); // Not owned edges included
     }
   }
 
-   rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT);
-   CHECK_ERR(rval);
-
-   my_cells_num = cells.size();
-   if (test_nb_cells && 2 == procs) {
-     if (0 == rank) {
-       CHECK_EQUAL(963, my_cells_num); // Gather set cells included
-       if (mixed_elements)
-         CHECK_EQUAL((size_t)4, cells.psize()); // Gather set cells included
-       else
-         CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included
-     }
-     else if (1 == rank) {
-       CHECK_EQUAL(321, my_cells_num); // Not owned cells excluded
-       CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells excluded
-     }
-   }
-
-  if (0 == rank) {
-    // Get gather set
-    EntityHandle gather_set;
-    ReadUtilIface* readUtilIface;
-    rval = mb.query_interface(readUtilIface);
-    CHECK_ERR(rval);
-    rval = readUtilIface->get_gather_set(gather_set);
-    CHECK_ERR(rval);
+  rval = pcomm->filter_pstatus(local_edges, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+  CHECK_ERR(rval);
 
-    // Get gather set entities
-    Range gather_ents;
-    rval = mb.get_entities_by_handle(gather_set, gather_ents);
-    CHECK_ERR(rval);
+  edges_num = local_edges.size();
+  if (2 == procs) {
+    if (rcbzoltan) {
+      if (0 == rank)
+        CHECK_EQUAL(1005, edges_num);
+      else if (1 == rank)
+        CHECK_EQUAL(915, edges_num); // Not owned edges excluded
+    }
+    else {
+      if (0 == rank)
+        CHECK_EQUAL(1438, edges_num);
+      else if (1 == rank)
+        CHECK_EQUAL(482, edges_num); // Not owned edges excluded
+    }
+  }
 
-    // Remove gather set vertices in processor 0
-    verts = subtract(verts, gather_ents);
+  // Get local cells
+  Range local_cells;
+  rval = mb.get_entities_by_type(0, MBPOLYGON, local_cells);
+  CHECK_ERR(rval);
 
-    // Remove gather set edges in processor 0
-    edges = subtract(edges, gather_ents);
+  int cells_num = local_cells.size();
+  if (2 == procs) {
+    CHECK_EQUAL(321, cells_num);
 
-    // Remove gather set cells in processor 0
-    cells = subtract(cells, gather_ents);
+    if (rcbzoltan) {
+      if (no_mixed_elements)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+      else
+        CHECK_EQUAL((size_t)2, local_cells.psize());
+     }
+    else {
+      if (0 == rank) {
+        if (no_mixed_elements)
+          CHECK_EQUAL((size_t)1, local_cells.psize());
+        else
+          CHECK_EQUAL((size_t)2, local_cells.psize());
+      }
+      else if (1 == rank)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+    }
   }
 
-  my_verts_num = verts.size();
-  if (test_nb_nodes && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(1120, my_verts_num); // Gather set vertices excluded
-    else if (1 == rank)
-      CHECK_EQUAL(160, my_verts_num); // Not owned vertices excluded
-  }
+  rval = pcomm->filter_pstatus(local_cells, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+  CHECK_ERR(rval);
 
-  std::cout << "proc: " << rank << " verts:" << my_verts_num << "\n";
+  cells_num = local_cells.size();
+  if (2 == procs) {
+    CHECK_EQUAL(321, cells_num);
 
-  int total_verts;
-  MPI_Reduce(&my_verts_num, &total_verts, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
-  if (0 == rank) {
-    std::cout << "total vertices: " << total_verts << "\n";
-    if (test_nb_nodes)
-      CHECK_EQUAL(total_verts, num_verts);
+    if (rcbzoltan) {
+      if (no_mixed_elements)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+      else
+        CHECK_EQUAL((size_t)2, local_cells.psize());
+    }
+    else {
+      if (0 == rank) {
+        if (no_mixed_elements)
+          CHECK_EQUAL((size_t)1, local_cells.psize());
+        else
+          CHECK_EQUAL((size_t)2, local_cells.psize());
+      }
+      else if (1 == rank)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+    }
   }
 
-  my_edges_num = edges.size();
-  if (test_nb_edges && 2 == procs) {
-    if (0 == rank)
-      CHECK_EQUAL(1438, my_edges_num); // Gather set edges excluded
-    else if (1 == rank)
-      CHECK_EQUAL(482, my_edges_num); // Not owned edges excluded
+  std::cout << "proc: " << rank << " verts:" << verts_num << "\n";
+
+  int total_verts_num;
+  MPI_Reduce(&verts_num, &total_verts_num, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
+  if (0 == rank) {
+    std::cout << "total vertices: " << total_verts_num << "\n";
+    CHECK_EQUAL(1280, total_verts_num);
   }
 
-  std::cout << "proc: " << rank << " edges:" << my_edges_num << "\n";
+  std::cout << "proc: " << rank << " edges:" << edges_num << "\n";
 
-  int total_edges;
-  MPI_Reduce(&my_edges_num, &total_edges, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
+  int total_edges_num;
+  MPI_Reduce(&edges_num, &total_edges_num, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
   if (0 == rank) {
-    std::cout << "total edges: " << total_edges << "\n";
-    if (test_nb_edges)
-      CHECK_EQUAL(total_edges, num_edges);
+    std::cout << "total edges: " << total_edges_num << "\n";
+    CHECK_EQUAL(1920, total_edges_num);
   }
 
-  my_cells_num = cells.size();
-  if (test_nb_cells && 2 == procs) {
-    if (0 == rank) {
-      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded
-      if (mixed_elements)
-        CHECK_EQUAL((size_t)2, cells.psize()); // Gather set cells excluded
-      else
-        CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded
-    }
-    else if (1 == rank) {
-      CHECK_EQUAL(321, my_cells_num); // Not owned cells excluded
-      CHECK_EQUAL((size_t)1, cells.psize()); // Not owned cells excluded
-    }
+  std::cout << "proc: " << rank << " cells:" << cells_num << "\n";
+
+  int total_cells_num;
+  MPI_Reduce(&cells_num, &total_cells_num, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
+  if (0 == rank) {
+    std::cout << "total cells: " << total_cells_num << "\n";
+    CHECK_EQUAL(642, total_cells_num);
   }
 
-   std::cout << "proc: " << rank << " cells:" << my_cells_num << "\n";
+#ifdef HDF5_PARALLEL
+  std::string write_options("PARALLEL=WRITE_PART;");
 
-   int total_cells;
-   MPI_Reduce(&my_cells_num, &total_cells, 1, MPI_INTEGER, MPI_SUM, 0, pcomm->proc_config().proc_comm());
-   if (0 == rank) {
-     std::cout << "total cells: " << total_cells << "\n";
-     if (test_nb_cells)
-       CHECK_EQUAL(total_cells, num_cells);
-   }
+  std::string output_file = "test_mpas";
+  if (rcbzoltan)
+    output_file += "_rcbzoltan";
+  if (no_mixed_elements)
+    output_file += "_no_mixed_elements";
+  output_file += ".h5m";
 
-  std::string write_options("PARALLEL=WRITE_PART;");
-  mb.write_file("test_mpas.h5m", NULL, write_options.c_str());
+  mb.write_file(output_file.c_str(), NULL, write_options.c_str());
+#endif
 }
 
-void test_multiple_loads_of_same_file()
+void gather_one_cell_var(int gather_set_rank)
 {
   Core moab;
   Interface& mb = moab;
+
   EntityHandle file_set;
-  ErrorCode rval;
-  rval = mb.create_meshset(MESHSET_SET, file_set);
+  ErrorCode rval = mb.create_meshset(MESHSET_SET, file_set);
   CHECK_ERR(rval);
 
-  // Read first only header information, no mesh, no variable
-  std::string opts("PARALLEL=READ_PART;PARTITION;NOMESH;VARIABLE=;PARTITION_METHOD=TRIVIAL");
-  rval = mb.load_file(example, &file_set, opts.c_str());
-  CHECK_ERR(rval);
+  read_options = "PARALLEL=READ_PART;PARTITION_METHOD=TRIVIAL;PARALLEL_RESOLVE_SHARED_ENTS";
+  std::ostringstream gather_set_option;
+  gather_set_option << ";GATHER_SET=" << gather_set_rank;
+  read_options += gather_set_option.str();
 
-  // Create mesh, no variable
-  opts="PARALLEL=READ_PART;PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARTITION_METHOD=TRIVIAL;VARIABLE=";
-  // Create gather set in processor 1
-  opts += std::string(";GATHER_SET=1");
-  rval = mb.load_file(example, &file_set, opts.c_str());
-  CHECK_ERR(rval);
-
-  // Read variable ke at timestep 0, no mesh
-  opts = "PARALLEL=READ_PART;PARTITION;PARTITION_METHOD=TRIVIAL;NOMESH;VARIABLE=ke;TIMESTEP=0";
-  rval = mb.load_file(example, &file_set, opts.c_str());
+  rval = mb.load_file(example, &file_set, read_options.c_str());
   CHECK_ERR(rval);
 
   ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
   int procs = pcomm->proc_config().proc_size();
   int rank = pcomm->proc_config().proc_rank();
 
-  // Make check runs this test in two processors
-  if (2 == procs) {
-    Range verts;
-    rval = mb.get_entities_by_type(0, MBVERTEX, verts);
-    CHECK_ERR(rval);
+  // Make sure gather_set_rank is valid
+  if (gather_set_rank < 0 || gather_set_rank >= procs)
+    return;
 
-    Range edges;
-    rval = mb.get_entities_by_type(0, MBEDGE, edges);
-    CHECK_ERR(rval);
+  Range cells, cells_owned;
+  rval = mb.get_entities_by_type(file_set, MBPOLYGON, cells);
+  CHECK_ERR(rval);
 
-    Range cells;
-    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+  // Get local owned cells
+  rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &cells_owned);
+  CHECK_ERR(rval);
+
+  EntityHandle gather_set = 0;
+  if (gather_set_rank == rank) {
+    // Get gather set
+    ReadUtilIface* readUtilIface;
+    mb.query_interface(readUtilIface);
+    rval = readUtilIface->get_gather_set(gather_set);
     CHECK_ERR(rval);
+    assert(gather_set != 0);
+  }
 
-    int my_verts_num = verts.size();
-    int my_edges_num = edges.size();
-    int my_cells_num = cells.size();
+  Tag ke_tag0, gid_tag;
+  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0, MB_TAG_DENSE);
+  CHECK_ERR(rval);
 
-    if (0 == rank) {
-      CHECK_EQUAL(1120, my_verts_num);
-      CHECK_EQUAL(1438, my_edges_num);
-      CHECK_EQUAL(321, my_cells_num);
-      CHECK_EQUAL((size_t)2, cells.psize());
-
-      const double eps = 1e-20;
-      double val[2];
-
-      // Check tag for cell variable ke at timestep 0
-      Tag ke_tag0;
-      rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
-      CHECK_ERR(rval);
-
-      // Check ke0 tag values on first pentagon and first hexagon
-      EntityHandle cell_ents[] = {cells[0], cells[12]};
-      rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-      CHECK_REAL_EQUAL(15.001, val[0], eps);
-      CHECK_REAL_EQUAL(16.013, val[1], eps);
-    }
-    else if (1 == rank) {
-      CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included
-      CHECK_EQUAL(3364, my_edges_num); // Gather set edges included; Not owned edges included
-      CHECK_EQUAL(963, my_cells_num); // Gather set cells included; Not owned cells included
-      CHECK_EQUAL((size_t)3, cells.psize()); // Gather set cells included; Not owned cells included
-
-      // Get gather set
-      EntityHandle gather_set;
-      ReadUtilIface* readUtilIface;
-      rval = mb.query_interface(readUtilIface);
-      CHECK_ERR(rval);
-      rval = readUtilIface->get_gather_set(gather_set);
-      CHECK_ERR(rval);
-
-      // Get gather set entities
-      Range gather_ents;
-      rval = mb.get_entities_by_handle(gather_set, gather_ents);
-      CHECK_ERR(rval);
-
-      // Remove gather set vertices in processor 1
-      verts = subtract(verts, gather_ents);
-      my_verts_num = verts.size();
-      CHECK_EQUAL(1122, my_verts_num); // Gather set vertices excluded; Not owned vertices included
-
-      // Remove gather set edges in processor 1
-      edges = subtract(edges, gather_ents);
-      my_edges_num = edges.size();
-      CHECK_EQUAL(1444, my_edges_num); // Gather set edges excluded; Not owned edges included
-
-      // Remove gather set cells in processor 1
-      cells = subtract(cells, gather_ents);
-      my_cells_num = cells.size();
-      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded; Not owned cells included
-      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded; Not owned cells included
-    }
+  rval = mb.tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_DENSE);
+  CHECK_ERR(rval);
+
+  pcomm->gather_data(cells_owned, ke_tag0, gid_tag, gather_set, gather_set_rank);
+
+  if (gather_set_rank == rank) {
+    // Get gather set cells
+    Range gather_set_cells;
+    rval = mb.get_entities_by_type(gather_set, MBPOLYGON, gather_set_cells);
+    CHECK_EQUAL((size_t)642, gather_set_cells.size());
+    CHECK_EQUAL((size_t)2, gather_set_cells.psize());
+
+    // Check ke0 tag values on 4 gather set cells: first pentagon, last pentagon,
+    // first hexagon and last hexagon
+    EntityHandle cell_ents[] = {gather_set_cells[0], gather_set_cells[11],
+                                gather_set_cells[12], gather_set_cells[641]};
+    double ke0_val[4];
+    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 4, ke0_val);
+
+    CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+    CHECK_REAL_EQUAL(15.012, ke0_val[1], eps);
+    CHECK_REAL_EQUAL(16.013, ke0_val[2], eps);
+    CHECK_REAL_EQUAL(16.642, ke0_val[3], eps);
   }
 }
 
-void test_multiple_loads_of_same_file_no_mixed_elements()
+void multiple_loads_of_same_file(bool no_mixed_elements)
 {
   Core moab;
   Interface& mb = moab;
+
+  // Need a file set for nomesh to work right
   EntityHandle file_set;
   ErrorCode rval;
   rval = mb.create_meshset(MESHSET_SET, file_set);
   CHECK_ERR(rval);
 
   // Read first only header information, no mesh, no variable
-  std::string opts("PARALLEL=READ_PART;PARTITION;NOMESH;VARIABLE=;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS");
-  rval = mb.load_file(example, &file_set, opts.c_str());
+  read_options = "PARALLEL=READ_PART;PARTITION;NOMESH;VARIABLE=;PARTITION_METHOD=TRIVIAL";
+  if (no_mixed_elements)
+    read_options += ";NO_MIXED_ELEMENTS";
+
+  rval = mb.load_file(example, &file_set, read_options.c_str());
   CHECK_ERR(rval);
 
   // Create mesh, no variable
-  opts="PARALLEL=READ_PART;PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS;VARIABLE=";
-  // Create gather set in processor 1
-  opts += std::string(";GATHER_SET=1");
-  rval = mb.load_file(example, &file_set, opts.c_str());
+  read_options = "PARALLEL=READ_PART;PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARTITION_METHOD=TRIVIAL;VARIABLE=";
+  if (no_mixed_elements)
+    read_options += ";NO_MIXED_ELEMENTS";
+
+  rval = mb.load_file(example, &file_set, read_options.c_str());
   CHECK_ERR(rval);
 
   // Read variable ke at timestep 0, no mesh
-  opts = "PARALLEL=READ_PART;PARTITION;PARTITION_METHOD=TRIVIAL;NO_MIXED_ELEMENTS;NOMESH;VARIABLE=ke;TIMESTEP=0";
-  rval = mb.load_file(example, &file_set, opts.c_str());
+  read_options = "PARALLEL=READ_PART;PARTITION;PARTITION_METHOD=TRIVIAL;NOMESH;VARIABLE=ke;TIMESTEP=0";
+  if (no_mixed_elements)
+    read_options += ";NO_MIXED_ELEMENTS";
+
+  rval = mb.load_file(example, &file_set, read_options.c_str());
+  CHECK_ERR(rval);
+
+  Range local_verts;
+  rval = mb.get_entities_by_type(file_set, MBVERTEX, local_verts);
+  CHECK_ERR(rval);
+
+  Range local_edges;
+  rval = mb.get_entities_by_type(file_set, MBEDGE, local_edges);
+  CHECK_ERR(rval);
+
+  Range local_cells;
+  rval = mb.get_entities_by_type(file_set, MBPOLYGON, local_cells);
   CHECK_ERR(rval);
 
   ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
   int procs = pcomm->proc_config().proc_size();
   int rank = pcomm->proc_config().proc_rank();
 
-  // Make check runs this test in two processors
+  // Make check runs this test on two processors
   if (2 == procs) {
-    Range verts;
-    rval = mb.get_entities_by_type(0, MBVERTEX, verts);
-    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)321, local_cells.size());
 
-    Range edges;
-    rval = mb.get_entities_by_type(0, MBEDGE, edges);
+    // Check tag for cell variable ke at timestep 0
+    Tag ke_tag0;
+    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
     CHECK_ERR(rval);
 
-    Range cells;
-    rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
+    // Get ke0 tag values on 3 local cells
+    EntityHandle cell_ents[] = {local_cells[0], local_cells[160], local_cells[320]};
+    double ke0_val[3];
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 3, ke0_val);
     CHECK_ERR(rval);
 
-    int my_verts_num = verts.size();
-    int my_edges_num = edges.size();
-    int my_cells_num = cells.size();
-
     if (0 == rank) {
-      CHECK_EQUAL(1120, my_verts_num);
-      CHECK_EQUAL(1438, my_edges_num);
-      CHECK_EQUAL(321, my_cells_num);
-      CHECK_EQUAL((size_t)1, cells.psize());
-
-      const double eps = 1e-20;
-      double val[2];
-
-      // Check tag for cell variable ke at timestep 0
-      Tag ke_tag0;
-      rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
-      CHECK_ERR(rval);
-
-      // Check ke0 tag values on first pentagon and first hexagon
-      EntityHandle cell_ents[] = {cells[0], cells[12]};
-      rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-      CHECK_REAL_EQUAL(15.001, val[0], eps);
-      CHECK_REAL_EQUAL(16.013, val[1], eps);
+      CHECK_EQUAL((size_t)1120, local_verts.size());
+      CHECK_EQUAL((size_t)1438, local_edges.size());
+      if (no_mixed_elements)
+        CHECK_EQUAL((size_t)1, local_cells.psize());
+      else
+        CHECK_EQUAL((size_t)2, local_cells.psize());
+
+      CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+      CHECK_REAL_EQUAL(16.161, ke0_val[1], eps);
+      CHECK_REAL_EQUAL(16.321, ke0_val[2], eps);
     }
     else if (1 == rank) {
-      CHECK_EQUAL(2402, my_verts_num); // Gather set vertices included; Not owned vertices included
-      CHECK_EQUAL(3364, my_edges_num); // Gather set edges included; Not owned edges included
-      CHECK_EQUAL(963, my_cells_num); // Gather set cells included; Not owned cells included
-      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells included; Not owned cells included
-
-      // Get gather set
-      EntityHandle gather_set;
-      ReadUtilIface* readUtilIface;
-      rval = mb.query_interface(readUtilIface);
-      CHECK_ERR(rval);
-      rval = readUtilIface->get_gather_set(gather_set);
-      CHECK_ERR(rval);
-
-      // Get gather set entities
-      Range gather_ents;
-      rval = mb.get_entities_by_handle(gather_set, gather_ents);
-      CHECK_ERR(rval);
-
-      // Remove gather set vertices in processor 1
-      verts = subtract(verts, gather_ents);
-      my_verts_num = verts.size();
-      CHECK_EQUAL(1122, my_verts_num); // Gather set vertices excluded; Not owned vertices included
-
-      // Remove gather set edges in processor 1
-      edges = subtract(edges, gather_ents);
-      my_edges_num = edges.size();
-      CHECK_EQUAL(1444, my_edges_num); // Gather set edges excluded; Not owned edges included
-
-      // Remove gather set cells in processor 1
-      cells = subtract(cells, gather_ents);
-      my_cells_num = cells.size();
-      CHECK_EQUAL(321, my_cells_num); // Gather set cells excluded; Not owned cells included
-      CHECK_EQUAL((size_t)1, cells.psize()); // Gather set cells excluded; Not owned cells included
+      CHECK_EQUAL((size_t)1122, local_verts.size());
+      CHECK_EQUAL((size_t)1444, local_edges.size());
+      CHECK_EQUAL((size_t)1, local_cells.psize());
+
+      CHECK_REAL_EQUAL(16.322, ke0_val[0], eps);
+      CHECK_REAL_EQUAL(16.482, ke0_val[1], eps);
+      CHECK_REAL_EQUAL(16.642, ke0_val[2], eps);
     }
   }
 }


https://bitbucket.org/fathomteam/moab/commits/35fedf96fb0e/
Changeset:   35fedf96fb0e
Branch:      None
User:        danwu
Date:        2013-11-11 17:19:51
Summary:     Merged fathomteam/moab into master
Affected #:  11 files

diff --git a/test/io/read_mpas_nc.cpp b/test/io/read_mpas_nc.cpp
index d6e886f..75923fd 100644
--- a/test/io/read_mpas_nc.cpp
+++ b/test/io/read_mpas_nc.cpp
@@ -25,7 +25,9 @@ void test_read_no_mixed_elements(); // Test read option NO_MIXED_ELEMENTS
 void test_read_no_edges(); // Test read option NO_EDGES
 void test_gather_onevar(); // Test gather set with one variable
 
-ErrorCode get_options(std::string& opts);
+void get_options(std::string& opts);
+
+const double eps = 1e-20;
 
 int main(int argc, char* argv[])
 {
@@ -63,10 +65,10 @@ void test_read_all()
   Interface& mb = moab;
 
   std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
+  get_options(opts);
 
-  rval = mb.load_file(example, NULL, opts.c_str());
+  // Read mesh and read all variables at all timesteps
+  ErrorCode rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
   int procs = 1;
@@ -75,8 +77,11 @@ void test_read_all()
   procs = pcomm->proc_config().proc_size();
 #endif
 
-  // Make check runs this test in one processor
+  // Make check runs this test on one processor
   if (1 == procs) {
+    // For each tag, check two values
+    double val[2];
+
     // Check tags for vertex variable vorticity
     Tag vorticity_tag0, vorticity_tag1;
     rval = mb.tag_get_handle("vorticity0", 1, MB_TYPE_DOUBLE, vorticity_tag0);
@@ -87,19 +92,18 @@ void test_read_all()
     // Get vertices (1280 edges)
     Range verts;
     rval = mb.get_entities_by_type(0, MBVERTEX, verts);
-    assert(rval == MB_SUCCESS);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)1280, verts.size());
     CHECK_EQUAL((size_t)1, verts.psize());
 
-    const double eps = 1e-20;
-    double val[2];
-
     // Check vorticity tag values on first two vertices
     EntityHandle vert_ents[] = {verts[0], verts[1]};
-    rval = mb.tag_get_data(vorticity_tag0, &vert_ents[0], 2, val);
+    rval = mb.tag_get_data(vorticity_tag0, vert_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(1.1, val[0], eps);
     CHECK_REAL_EQUAL(1.2, val[1], eps);
-    rval = mb.tag_get_data(vorticity_tag1, &vert_ents[0], 2, val);
+    rval = mb.tag_get_data(vorticity_tag1, vert_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(2.1, val[0], eps);
     CHECK_REAL_EQUAL(2.2, val[1], eps);
 
@@ -113,16 +117,18 @@ void test_read_all()
     // Get edges (1920 edges)
     Range edges;
     rval = mb.get_entities_by_type(0, MBEDGE, edges);
-    assert(rval == MB_SUCCESS);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)1920, edges.size());
     CHECK_EQUAL((size_t)1, edges.psize());
 
     // Check u tag values on two specified edges
     EntityHandle edge_ents[] = {edges[5], edges[6]};
-    rval = mb.tag_get_data(u_tag0, &edge_ents[0], 2, val);
+    rval = mb.tag_get_data(u_tag0, edge_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(1.113138721544778, val[0], eps);
     CHECK_REAL_EQUAL(-1.113138721930009, val[1], eps);
-    rval = mb.tag_get_data(u_tag1, &edge_ents[0], 2, val);
+    rval = mb.tag_get_data(u_tag1, edge_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(2.113138721544778, val[0], eps);
     CHECK_REAL_EQUAL(-2.113138721930009, val[1], eps);
 
@@ -136,7 +142,7 @@ void test_read_all()
     // Get cells (12 pentagons and 630 hexagons)
     Range cells;
     rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
-    assert(rval == MB_SUCCESS);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)642, cells.size());
 #ifdef USE_MPI
     // If MOAB is compiled parallel, sequence size requested are increased
@@ -149,10 +155,12 @@ void test_read_all()
 
     // Check ke tag values on first pentagon and first hexagon
     EntityHandle cell_ents[] = {cells[0], cells[12]};
-    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(15.001, val[0], eps);
     CHECK_REAL_EQUAL(16.013, val[1], eps);
-    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
+    rval = mb.tag_get_data(ke_tag1, cell_ents, 2, val);
+    CHECK_ERR(rval);
     CHECK_REAL_EQUAL(25.001, val[0], eps);
     CHECK_REAL_EQUAL(26.013, val[1], eps);
   }
@@ -162,12 +170,13 @@ void test_read_onevar()
 {
   Core moab;
   Interface& mb = moab;
+
   std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
+  get_options(opts);
 
-  opts += std::string(";VARIABLE=ke");
-  rval = mb.load_file(example, NULL, opts.c_str());
+  // Read mesh and read cell variable ke at all timesteps
+  opts += ";VARIABLE=ke";
+  ErrorCode rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
   int procs = 1;
@@ -176,9 +185,9 @@ void test_read_onevar()
   procs = pcomm->proc_config().proc_size();
 #endif
 
-  // Make check runs this test in one processor
+  // Make check runs this test on one processor
   if (1 == procs) {
-    // Check for proper tags
+    // Check ke tags
     Tag ke_tag0, ke_tag1;
     rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
     CHECK_ERR(rval);
@@ -188,7 +197,7 @@ void test_read_onevar()
     // Get cells (12 pentagons and 630 hexagons)
     Range cells;
     rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
-    assert(rval == MB_SUCCESS);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)642, cells.size());
 
 #ifdef USE_MPI
@@ -200,16 +209,23 @@ void test_read_onevar()
     CHECK_EQUAL((size_t)1, cells.psize());
 #endif
 
-    // Check ke tag values on first pentagon and first hexagon
-    const double eps = 1e-20;
-    double val[2];
-    EntityHandle cell_ents[] = {cells[0], cells[12]};
-    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(15.001, val[0], eps);
-    CHECK_REAL_EQUAL(16.013, val[1], eps);
-    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(25.001, val[0], eps);
-    CHECK_REAL_EQUAL(26.013, val[1], eps);
+    // Check ke tag values on 4 cells: first pentagon, last pentagon,
+    // first hexagon, and last hexagon
+    EntityHandle cell_ents[] = {cells[0], cells[11], cells[12], cells[641]};
+    double ke0_val[4];
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 4, ke0_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+    CHECK_REAL_EQUAL(15.012, ke0_val[1], eps);
+    CHECK_REAL_EQUAL(16.013, ke0_val[2], eps);
+    CHECK_REAL_EQUAL(16.642, ke0_val[3], eps);
+    double ke1_val[4];
+    rval = mb.tag_get_data(ke_tag1, cell_ents, 4, ke1_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(25.001, ke1_val[0], eps);
+    CHECK_REAL_EQUAL(25.012, ke1_val[1], eps);
+    CHECK_REAL_EQUAL(26.013, ke1_val[2], eps);
+    CHECK_REAL_EQUAL(26.642, ke1_val[3], eps);
   }
 }
 
@@ -217,19 +233,21 @@ void test_read_onetimestep()
 {
   Core moab;
   Interface& mb = moab;
+
   std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
+  get_options(opts);
 
-  opts += std::string(";TIMESTEP=1");
-  rval = mb.load_file(example, NULL, opts.c_str());
+  // Read mesh and read all variables at 2nd timestep
+  opts += ";TIMESTEP=1";
+  ErrorCode rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tags
-  Tag ke_tag0, ke_tag1;
-  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+  // Check vorticity tags
+  Tag vorticity_tag0, vorticity_tag1;
+  rval = mb.tag_get_handle("vorticity0", 1, MB_TYPE_DOUBLE, vorticity_tag0);
+  // Tag vorticity0 should not exist
   CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
-  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+  rval = mb.tag_get_handle("vorticity1", 1, MB_TYPE_DOUBLE, vorticity_tag1);
   CHECK_ERR(rval);
 }
 
@@ -238,33 +256,35 @@ void test_read_nomesh()
   Core moab;
   Interface& mb = moab;
 
-  // Need a set for nomesh to work right
-  EntityHandle set;
-  ErrorCode rval = mb.create_meshset(MESHSET_SET, set);
+  // Need a file set for nomesh to work right
+  EntityHandle file_set;
+  ErrorCode rval = mb.create_meshset(MESHSET_SET, file_set);
   CHECK_ERR(rval);
 
   std::string orig, opts;
-  rval = get_options(orig);
-  CHECK_ERR(rval);
+  get_options(orig);
 
-  opts = orig + std::string(";TIMESTEP=0");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read mesh and read all variables at 1st timestep
+  opts = orig + ";TIMESTEP=0";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tags
-  Tag ke_tag0, ke_tag1;
-  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+  // Check u tags
+  Tag u_tag0, u_tag1;
+  rval = mb.tag_get_handle("u0", 1, MB_TYPE_DOUBLE, u_tag0);
   CHECK_ERR(rval);
-  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+  // Tag u1 should not exist
+  rval = mb.tag_get_handle("u1", 1, MB_TYPE_DOUBLE, u_tag1);
   CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
 
-  // Now read 2nd timestep with nomesh option
-  opts = orig + std::string(";TIMESTEP=1;NOMESH");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read all variables at 2nd timestep 0, no need to read mesh
+  opts = orig + ";TIMESTEP=1;NOMESH";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tag
-  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+  // Check tag u1 again
+  rval = mb.tag_get_handle("u1", 1, MB_TYPE_DOUBLE, u_tag1);
+  // Tag u1 should exist at this time
   CHECK_ERR(rval);
 }
 
@@ -273,58 +293,111 @@ void test_read_novars()
   Core moab;
   Interface& mb = moab;
 
-  // Need a set for nomesh to work right
-  EntityHandle set;
-  ErrorCode rval = mb.create_meshset(MESHSET_SET, set);
+  // Need a file set for nomesh to work right
+  EntityHandle file_set;
+  ErrorCode rval = mb.create_meshset(MESHSET_SET, file_set);
   CHECK_ERR(rval);
 
   std::string orig, opts;
-  rval = get_options(orig);
+  get_options(orig);
   CHECK_ERR(rval);
 
-  opts = orig + std::string(";NOMESH;VARIABLE=");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read header info only, no mesh, no variables
+  opts = orig + ";NOMESH;VARIABLE=";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  opts = orig + std::string(";VARIABLE=;TIMESTEP=0");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read mesh, but still no variables
+  opts = orig + ";VARIABLE=;TIMESTEP=0";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tag
+  // Check ke tags
   Tag ke_tag0, ke_tag1;
   rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+  // Tag ke0 should not exist
+  CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+  rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+  // Tag ke1 should not exist
   CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
 
-  opts = orig + std::string(";VARIABLE=ke;TIMESTEP=0;NOMESH");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read ke at 1st timestep, no need to read mesh
+  opts = orig + ";VARIABLE=ke;TIMESTEP=0;NOMESH";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tags
+  // Check ke tags again
   rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+  // Tag ke0 should exist at this time
   CHECK_ERR(rval);
+  // Tag ke1 should still not exist
   rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
   CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
 
-  // Now read 2nd timestep with nomesh option
-  opts = orig + std::string(";VARIABLE=ke;TIMESTEP=1;NOMESH");
-  rval = mb.load_file(example, &set, opts.c_str());
+  // Read ke at 2nd timestep, no need to read mesh
+  opts = orig + ";VARIABLE=ke;TIMESTEP=1;NOMESH";
+  rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
-  // Check for proper tag
+  // Check tag ke1 again
   rval = mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+  // Tag ke1 should exist at this time
   CHECK_ERR(rval);
+
+  int procs = 1;
+#ifdef USE_MPI
+  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
+  procs = pcomm->proc_config().proc_size();
+#endif
+
+  // Make check runs this test on one processor
+  if (1 == procs) {
+    // Get cells (12 pentagons and 630 hexagons)
+    Range cells;
+    rval = mb.get_entities_by_type(file_set, MBPOLYGON, cells);
+    CHECK_ERR(rval);
+    CHECK_EQUAL((size_t)642, cells.size());
+
+#ifdef USE_MPI
+    // If MOAB is compiled parallel, sequence size requested are increased
+    // by a factor of 1.5, to allow for ghosts. This will introduce a gap
+    // between the two face sequences.
+    CHECK_EQUAL((size_t)2, cells.psize());
+#else
+    CHECK_EQUAL((size_t)1, cells.psize());
+#endif
+
+    // Check ke tag values on 4 cells: first pentagon, last pentagon,
+    // first hexagon, and last hexagon
+    EntityHandle cell_ents[] = {cells[0], cells[11], cells[12], cells[641]};
+    double ke0_val[4];
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 4, ke0_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+    CHECK_REAL_EQUAL(15.012, ke0_val[1], eps);
+    CHECK_REAL_EQUAL(16.013, ke0_val[2], eps);
+    CHECK_REAL_EQUAL(16.642, ke0_val[3], eps);
+    double ke1_val[4];
+    rval = mb.tag_get_data(ke_tag1, cell_ents, 4, ke1_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(25.001, ke1_val[0], eps);
+    CHECK_REAL_EQUAL(25.012, ke1_val[1], eps);
+    CHECK_REAL_EQUAL(26.013, ke1_val[2], eps);
+    CHECK_REAL_EQUAL(26.642, ke1_val[3], eps);
+  }
 }
 
 void test_read_no_mixed_elements()
 {
   Core moab;
   Interface& mb = moab;
+
   std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
+  get_options(opts);
 
-  opts += std::string(";NO_MIXED_ELEMENTS;VARIABLE=ke");
-  rval = mb.load_file(example, NULL, opts.c_str());
+  // Read mesh with no mixed elements and read all variables at all timesteps
+  opts += ";NO_MIXED_ELEMENTS";
+  ErrorCode rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
   int procs = 1;
@@ -333,9 +406,9 @@ void test_read_no_mixed_elements()
   procs = pcomm->proc_config().proc_size();
 #endif
 
-  // Make check runs this test in one processor
+  // Make check runs this test on one processor
   if (1 == procs) {
-    // Check for proper tags
+    // Check ke tags
     Tag ke_tag0, ke_tag1;
     rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
     CHECK_ERR(rval);
@@ -345,23 +418,29 @@ void test_read_no_mixed_elements()
     // Get cells (12 pentagons and 630 hexagons)
     Range cells;
     rval = mb.get_entities_by_type(0, MBPOLYGON, cells);
-    assert(rval == MB_SUCCESS);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)642, cells.size());
     // Only one group of cells (pentagons are padded to hexagons,
     // e.g. connectivity [1 2 3 4 5] => [1 2 3 4 5 5])
     CHECK_EQUAL((size_t)1, cells.psize());
 
-    const double eps = 1e-20;
-    double val[2];
-
-    // Check ke tag values on first pentagon and first hexagon
-    EntityHandle cell_ents[] = {cells[0], cells[12]};
-    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(15.001, val[0], eps);
-    CHECK_REAL_EQUAL(16.013, val[1], eps);
-    rval = mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(25.001, val[0], eps);
-    CHECK_REAL_EQUAL(26.013, val[1], eps);
+    // Check ke tag values on 4 cells: first pentagon, last pentagon,
+    // first hexagon, and last hexagon
+    EntityHandle cell_ents[] = {cells[0], cells[11], cells[12], cells[641]};
+    double ke0_val[4];
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 4, ke0_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+    CHECK_REAL_EQUAL(15.012, ke0_val[1], eps);
+    CHECK_REAL_EQUAL(16.013, ke0_val[2], eps);
+    CHECK_REAL_EQUAL(16.642, ke0_val[3], eps);
+    double ke1_val[4];
+    rval = mb.tag_get_data(ke_tag1, cell_ents, 4, ke1_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(25.001, ke1_val[0], eps);
+    CHECK_REAL_EQUAL(25.012, ke1_val[1], eps);
+    CHECK_REAL_EQUAL(26.013, ke1_val[2], eps);
+    CHECK_REAL_EQUAL(26.642, ke1_val[3], eps);
   }
 }
 
@@ -369,107 +448,98 @@ void test_read_no_edges()
 {
   Core moab;
   Interface& mb = moab;
+
   std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
+  get_options(opts);
 
-  opts += std::string(";NO_EDGES;VARIABLE=");
-  rval = mb.load_file(example, NULL, opts.c_str());
+  opts += ";NO_EDGES;VARIABLE=";
+  ErrorCode rval = mb.load_file(example, NULL, opts.c_str());
   CHECK_ERR(rval);
 
-  int procs = 1;
-#ifdef USE_MPI
-  ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
-  procs = pcomm->proc_config().proc_size();
-#endif
-
-  // Make check runs this test in one processor
-  if (1 == procs) {
-    // Get edges
-    Range edges;
-    rval = mb.get_entities_by_type(0, MBEDGE, edges);
-    assert(rval == MB_SUCCESS);
-    CHECK_EQUAL((size_t)0, edges.size());
-  }
+  // Get edges
+  Range edges;
+  rval = mb.get_entities_by_type(0, MBEDGE, edges);
+  CHECK_ERR(rval);
+  CHECK_EQUAL((size_t)0, edges.size());
 }
 
 void test_gather_onevar()
 {
   Core moab;
   Interface& mb = moab;
-  std::string opts;
-  ErrorCode rval = get_options(opts);
-  CHECK_ERR(rval);
 
   EntityHandle file_set;
-  rval = mb.create_meshset(MESHSET_SET, file_set);
+  ErrorCode rval = mb.create_meshset(MESHSET_SET, file_set);
   CHECK_ERR(rval);
 
-  // Get cell variable ke
-  opts += std::string(";VARIABLE=ke;");
-  // Create gather set
-  opts += std::string(";GATHER_SET=0;");
+  std::string opts;
+  get_options(opts);
+
+  // Read cell variable ke and create gather set on processor 0
+  opts += ";VARIABLE=ke;GATHER_SET=0";
   rval = mb.load_file(example, &file_set, opts.c_str());
   CHECK_ERR(rval);
 
 #ifdef USE_MPI
   ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
-  int procs = pcomm->proc_config().proc_size();
+  int rank = pcomm->proc_config().proc_rank();
 
-  // Make check runs this test in one processor
-  if (1 == procs) {
-    Range cells, cells_owned;
-    rval = mb.get_entities_by_type(file_set, MBPOLYGON, cells);
-    CHECK_ERR(rval);
+  Range cells, cells_owned;
+  rval = mb.get_entities_by_type(file_set, MBPOLYGON, cells);
+  CHECK_ERR(rval);
 
-    // Get locally owned cells
-    rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &cells_owned);
-    CHECK_ERR(rval);
-    CHECK_EQUAL((size_t)642, cells_owned.size());
-    CHECK_EQUAL((size_t)2, cells_owned.psize());
+  // Get local owned cells
+  rval = pcomm->filter_pstatus(cells, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &cells_owned);
+  CHECK_ERR(rval);
 
+  EntityHandle gather_set = 0;
+  if (0 == rank) {
     // Get gather set
-    EntityHandle gather_set;
     ReadUtilIface* readUtilIface;
     mb.query_interface(readUtilIface);
     rval = readUtilIface->get_gather_set(gather_set);
     CHECK_ERR(rval);
+    assert(gather_set != 0);
+  }
 
-    Tag ke_tag0, gid_tag;
-    rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0, MB_TAG_DENSE);
-    CHECK_ERR(rval);
+  Tag ke_tag0, gid_tag;
+  rval = mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0, MB_TAG_DENSE);
+  CHECK_ERR(rval);
 
-    rval = mb.tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_DENSE);
-    CHECK_ERR(rval);
+  rval = mb.tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_DENSE);
+  CHECK_ERR(rval);
 
-    pcomm->gather_data(cells_owned, ke_tag0, gid_tag, gather_set);
+  pcomm->gather_data(cells_owned, ke_tag0, gid_tag, gather_set, 0);
 
+  if (0 == rank) {
     // Get gather set cells
     Range gather_set_cells;
     rval = mb.get_entities_by_type(gather_set, MBPOLYGON, gather_set_cells);
+    CHECK_ERR(rval);
     CHECK_EQUAL((size_t)642, gather_set_cells.size());
     CHECK_EQUAL((size_t)2, gather_set_cells.psize());
 
-    const double eps = 1e-20;
-    double val[2];
-
-    // Check ke0 tag values on first pentagon and first hexagon of the gather set cells
-    EntityHandle cell_ents[] = {gather_set_cells[0], gather_set_cells[12]};
-    rval = mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
-    CHECK_REAL_EQUAL(15.001, val[0], eps);
-    CHECK_REAL_EQUAL(16.013, val[1], eps);
+    // Check ke0 tag values on 4 gather set cells: first pentagon, last pentagon,
+    // first hexagon, and last hexagon
+    double ke0_val[4];
+    EntityHandle cell_ents[] = {gather_set_cells[0], gather_set_cells[11],
+                                gather_set_cells[12], gather_set_cells[641]};
+    rval = mb.tag_get_data(ke_tag0, cell_ents, 4, ke0_val);
+    CHECK_ERR(rval);
+    CHECK_REAL_EQUAL(15.001, ke0_val[0], eps);
+    CHECK_REAL_EQUAL(15.012, ke0_val[1], eps);
+    CHECK_REAL_EQUAL(16.013, ke0_val[2], eps);
+    CHECK_REAL_EQUAL(16.642, ke0_val[3], eps);
   }
 #endif
 }
 
-ErrorCode get_options(std::string& opts)
+void get_options(std::string& opts)
 {
 #ifdef USE_MPI
   // Use parallel options
   opts = std::string(";;PARALLEL=READ_PART;PARTITION_METHOD=TRIVIAL");
-  return MB_SUCCESS;
 #else
   opts = std::string(";;");
-  return MB_SUCCESS;
 #endif
 }

diff --git a/tools/mbcoupler/Coupler.cpp b/tools/mbcoupler/Coupler.cpp
index 28f67ca..8d968c5 100644
--- a/tools/mbcoupler/Coupler.cpp
+++ b/tools/mbcoupler/Coupler.cpp
@@ -416,11 +416,17 @@ ErrorCode Coupler::locate_points(double *xyz, int num_points,
   unsigned int local_pts = 0;
   for (unsigned int i = 0; i < source_pts.get_n(); i++) {
     if (-1 != source_pts.vi_rd[3*i+2]) { //why bother sending message saying "i don't have the point" if it gets discarded?
-      //if (source_pts.vi_rd[3*i] == (int)my_rank) local_pts++;
       int tgt_index = 3*source_pts.vi_rd[3*i+1];
-      tl_tmp->vi_wr[tgt_index]   = source_pts.vi_rd[3*i];
-      tl_tmp->vi_wr[tgt_index+1] = source_pts.vi_rd[3*i+1];
-      tl_tmp->vi_wr[tgt_index+2] = source_pts.vi_rd[3*i+2];
+      // prefer always entities that are local, from the source_pts
+      // if a local entity was already found to contain the target point, skip
+      // tl_tmp->vi_wr[tgt_index] is -1 initially, but it could already be set with
+      // a remote processor
+      if (tl_tmp->vi_wr[tgt_index] != (int)my_rank)
+      {
+        tl_tmp->vi_wr[tgt_index]   = source_pts.vi_rd[3*i];
+        tl_tmp->vi_wr[tgt_index+1] = source_pts.vi_rd[3*i+1];
+        tl_tmp->vi_wr[tgt_index+2] = source_pts.vi_rd[3*i+2];
+      }
     }
   }
 

diff --git a/tools/mbcslam/CslamUtils.hpp b/tools/mbcslam/CslamUtils.hpp
index 0f9b573..bc1223d 100644
--- a/tools/mbcslam/CslamUtils.hpp
+++ b/tools/mbcslam/CslamUtils.hpp
@@ -15,6 +15,8 @@
 #define MAXEDGES 10
 #define MAXEDGES2 20 // used for coordinates in plane
 
+#define CORRTAGNAME "__correspondent"
+
 namespace moab
 {
 double dist2(double * a, double * b);

diff --git a/tools/mbcslam/Intx2Mesh.cpp b/tools/mbcslam/Intx2Mesh.cpp
index d9db131..74f65ff 100644
--- a/tools/mbcslam/Intx2Mesh.cpp
+++ b/tools/mbcslam/Intx2Mesh.cpp
@@ -18,11 +18,16 @@
 
 namespace moab {
 
-Intx2Mesh::Intx2Mesh(Interface * mbimpl):mb(mbimpl), parcomm(NULL), myTree(NULL)
+Intx2Mesh::Intx2Mesh(Interface * mbimpl):mb(mbimpl), parcomm(NULL), myTree(NULL), remote_cells(NULL)
 {
   dbg_1=0;
   box_error=0;
   my_rank=0;
+  BlueFlagTag=0;
+  RedFlagTag=0;
+  redParentTag =0;
+  blueParentTag = 0;
+  countTag = 0;
 }
 
 Intx2Mesh::~Intx2Mesh()
@@ -31,6 +36,15 @@ Intx2Mesh::~Intx2Mesh()
 }
 void Intx2Mesh::createTags()
 {
+  if (redParentTag)
+    mb->tag_delete(redParentTag);
+  if(blueParentTag)
+    mb->tag_delete(blueParentTag);
+  if (countTag)
+    mb->tag_delete(countTag);
+    /*RedEdges.clear();
+    localEnts.clear()*/
+
   unsigned char def_data_bit = 0; // unused by default
   ErrorCode rval = mb->tag_get_handle("blueFlag", 1, MB_TYPE_BIT, BlueFlagTag,
       MB_TAG_CREAT, &def_data_bit);
@@ -409,6 +423,12 @@ void Intx2Mesh::clean()
   mb->tag_delete(RedFlagTag);// to mark blue quads already considered
   mb->tag_delete(BlueFlagTag);
 
+  /*mb->tag_delete(redParentTag);
+  mb->tag_delete(blueParentTag);
+  mb->tag_delete(countTag);
+  RedEdges.clear();
+  localEnts.clear();*/
+
 }
 ErrorCode Intx2Mesh::initialize_local_kdtree(EntityHandle euler_set)
 {
@@ -817,7 +837,7 @@ ErrorCode Intx2Mesh::create_departure_mesh(EntityHandle & covering_lagr_set)
   // the elements are already in localEnts; get all vertices, and DP and LOC tag
   // get the DP tag , and get the departure points
   std::map<int, EntityHandle> globalID_to_handle;
-  std::map<int, EntityHandle> globalID_to_eh;
+/*  std::map<int, EntityHandle> globalID_to_eh;*/
   std::map<int, Range> rs;
   std::set<int> ps; // processors working with my_rank
   Tag dpTag = 0;
@@ -1051,34 +1071,19 @@ ErrorCode Intx2Mesh::create_departure_mesh(EntityHandle & covering_lagr_set)
 
   return MB_SUCCESS;
 }
-
-ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, EntityHandle & covering_lagr_set)
+ErrorCode Intx2Mesh::build_processor_euler_boxes(EntityHandle euler_set, Range & local_verts)
 {
-  // compute the bounding box on each proc
-  parcomm = ParallelComm::get_pcomm(mb, 0);
-  if (NULL==parcomm)
-    return MB_FAILURE;
-
   localEnts.clear();
   ErrorCode rval = mb->get_entities_by_dimension(euler_set, 2, localEnts);
   ERRORR(rval, "can't get ents by dimension");
 
-  Tag dpTag = 0;
-  std::string tag_name("DP");
-  rval = mb->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE);
-  ERRORR(rval, "can't get DP tag");
-  // get all local verts
-  Range local_verts;
   rval = mb->get_connectivity(localEnts, local_verts);
   int num_local_verts = (int) local_verts.size();
   ERRORR(rval, "can't get local vertices");
 
-  Tag gid;
-  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE);
-  ERRORR(rval,"can't get global ID tag" );
-  std::vector<int> gids(num_local_verts);
-  rval = mb->tag_get_data(gid, local_verts, &gids[0]);
-  ERRORR(rval, "can't get local vertices gids");
+  parcomm = ParallelComm::get_pcomm(mb, 0);
+  if (NULL==parcomm)
+    return MB_FAILURE;
 
   // get the position of local vertices, and decide local boxes (allBoxes...)
   double bmin[3]={DBL_MAX, DBL_MAX, DBL_MAX};
@@ -1086,6 +1091,7 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
 
   std::vector<double> coords(3*num_local_verts);
   rval = mb->get_coords(local_verts, &coords[0]);
+  ERRORR(rval, "can't get coords of vertices ");
 
   for (int i=0; i< num_local_verts; i++)
   {
@@ -1115,8 +1121,25 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
                                parcomm->proc_config().proc_comm());
   if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
 
+  // also process the max number of vertices per cell (4 for quads, but could be more for polygons)
+  int local_max_edges = 3;
+  for (Range::iterator it = localEnts.begin(); it!=localEnts.end(); it++)
+  {
+    const EntityHandle * conn;
+    int num_nodes;
+    rval = mb->get_connectivity(*it, conn, num_nodes);
+    ERRORR(rval, "can't get connectivity");
+    if (num_nodes>local_max_edges)
+      local_max_edges = num_nodes;
+  }
+
+  // now reduce max_edges over all processors
+  mpi_err = MPI_Allreduce(&local_max_edges, &max_edges, 1, MPI_INTEGER, MPI_MAX, parcomm->proc_config().proc_comm());
+  if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
+
   if (my_rank==0)
   {
+    std::cout << " maximum number of vertices per cell is " << max_edges << "\n";
     for (int i=0; i<numprocs; i++)
     {
       std::cout<<"proc: " << i << " box min: " << allBoxes[6*i  ] << " " <<allBoxes[6*i+1] << " " << allBoxes[6*i+2]  << " \n";
@@ -1124,14 +1147,46 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
     }
   }
 
+  return MB_SUCCESS;
+}
+ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, EntityHandle & covering_lagr_set)
+{
+  // compute the bounding box on each proc
+  parcomm = ParallelComm::get_pcomm(mb, 0);
+  if (NULL==parcomm)
+    return MB_FAILURE;
+
+  localEnts.clear();
+  ErrorCode rval = mb->get_entities_by_dimension(euler_set, 2, localEnts);
+  ERRORR(rval, "can't get ents by dimension");
+
+  Tag dpTag = 0;
+  std::string tag_name("DP");
+  rval = mb->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE);
+  ERRORR(rval, "can't get DP tag");
+  // get all local verts
+  Range local_verts;
+  rval = mb->get_connectivity(localEnts, local_verts);
+  int num_local_verts = (int) local_verts.size();
+  ERRORR(rval, "can't get local vertices");
+
+  rval = build_processor_euler_boxes(euler_set, local_verts);
+  ERRORR(rval, "can't build processor boxes");
+  Tag gid;
+  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE);
+  ERRORR(rval,"can't get global ID tag" );
+  std::vector<int> gids(num_local_verts);
+  rval = mb->tag_get_data(gid, local_verts, &gids[0]);
+  ERRORR(rval, "can't get local vertices gids");
 
   // now see the departure points; to what boxes should we send them?
   std::vector<double> dep_points(3*num_local_verts);
   rval = mb->tag_get_data(dpTag, local_verts, (void*)&dep_points[0]);
   ERRORR(rval, "can't get DP tag values");
   // ranges to send to each processor; will hold vertices and elements (quads?)
-  // will look if the box of the dep quad covers box of of euler mesh on proc (with tolerances)
+  // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances)
   std::map<int, Range> Rto;
+  int numprocs=parcomm->proc_config().proc_size();
 
   for (Range::iterator eit = localEnts.begin(); eit!=localEnts.end(); eit++)
   {
@@ -1189,8 +1244,8 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
   TLv.initialize(2, 0, 0, 3, numv); // to proc, GLOBAL ID, DP points
   TLv.enableWriteAccess();
 
-  int sizeTuple = 2+MAXEDGES; // max edges is now 10 :) for polygons
-  TLq.initialize(12, 0, 0, 0, numq); // to proc, elem GLOBAL ID, connectivity[10] (global ID v)
+  int sizeTuple = 2+max_edges; // determined earlier
+  TLq.initialize(2+max_edges, 0, 0, 0, numq); // to proc, elem GLOBAL ID, connectivity[10] (global ID v)
   TLq.enableWriteAccess();
   std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n";
 
@@ -1226,8 +1281,8 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
       TLq.vi_wr[sizeTuple*n+1] = global_id; // global id of element, used to identify it ...
       const EntityHandle * conn4;
       int num_nodes;
-      rval = mb->get_connectivity(q, conn4, num_nodes);// could be up to 10;
-      ERRORR(rval, "can't get connectivity for quad");
+      rval = mb->get_connectivity(q, conn4, num_nodes);// could be up to MAXEDGES, but it is limited by max_edges
+      ERRORR(rval, "can't get connectivity for cell");
       if (num_nodes > MAXEDGES)
         ERRORR(MB_FAILURE, "too many nodes in a polygon");
       for (int i=0; i<num_nodes; i++)
@@ -1236,7 +1291,7 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
         unsigned int index = local_verts.find(v)-local_verts.begin();
         TLq.vi_wr[sizeTuple*n+2+i] = gids[index];
       }
-      for (int k=num_nodes; k<MAXEDGES; k++)
+      for (int k=num_nodes; k<max_edges; k++)
       {
         TLq.vi_wr[sizeTuple*n+2+k] = 0; // fill the rest of node ids with 0; we know that the node ids start from 1!
       }
@@ -1245,7 +1300,7 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
     }
 
   }
-  // now we can route them to each processor
+
   // now we are done populating the tuples; route them to the appropriate processors
   (parcomm->proc_config().crystal_router())->gs_transfer(1, TLv, 0);
   (parcomm->proc_config().crystal_router())->gs_transfer(1, TLq, 0);
@@ -1253,7 +1308,8 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
 
   // maps from global ids to new vertex and quad handles, that are added
   std::map<int, EntityHandle> globalID_to_handle;
-  std::map<int, EntityHandle> globalID_to_eh;
+  /*std::map<int, EntityHandle> globalID_to_eh;*/
+  globalID_to_eh.clear();// need for next iteration
   // now, look at every TLv, and see if we have to create a vertex there or not
   int n=TLv.get_n();// the size of the points received
   for (int i=0; i<n; i++)
@@ -1328,7 +1384,7 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
       // construct the conn quad
       EntityHandle new_conn[MAXEDGES];
       int nnodes;
-      for (int j=0; j<MAXEDGES; j++)
+      for (int j=0; j<max_edges; j++)
       {
         int vgid = TLq.vi_rd[sizeTuple*i+2+j];// vertex global ID
         if (vgid==0)
@@ -1356,6 +1412,298 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
   }
   return MB_SUCCESS;
 }
+
+// this algorithm assumes lagr set is already created, and some elements will be coming from
+// other procs, and populate the covering_set
+// we need to keep in a tuple list the remote cells from other procs, because we need to send back
+// the intersection info (like area of the intx polygon, and the current concentration) maybe total
+// mass in that intx
+ErrorCode Intx2Mesh::create_departure_mesh_3rd_alg(EntityHandle & lagr_set,
+    EntityHandle & covering_set)
+{
+  EntityHandle dum = 0;
+
+  Tag corrTag;
+  ErrorCode rval = mb->tag_get_handle(CORRTAGNAME,
+                                           1, MB_TYPE_HANDLE, corrTag,
+                                           MB_TAG_DENSE, &dum);
+  //start copy from 2nd alg
+  // compute the bounding box on each proc
+  parcomm = ParallelComm::get_pcomm(mb, 0);
+  if (NULL == parcomm || ( 1==parcomm->proc_config().proc_size()))
+  {
+    covering_set = lagr_set; // nothing to communicate, it must be serial
+    return MB_SUCCESS;
+  }
+
+  // get all local verts
+  Range local_verts;
+  rval = mb->get_connectivity(localEnts, local_verts);
+  int num_local_verts = (int) local_verts.size();
+  ERRORR(rval, "can't get local vertices");
+
+  Tag gid;
+  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid,
+      MB_TAG_DENSE);
+  ERRORR(rval, "can't get global ID tag");
+  std::vector<int> gids(num_local_verts);
+  rval = mb->tag_get_data(gid, local_verts, &gids[0]);
+  ERRORR(rval, "can't get local vertices gids");
+
+  Range localDepCells;
+  rval = mb->get_entities_by_dimension(lagr_set, 2, localDepCells);
+  ERRORR(rval, "can't get ents by dimension from lagr set");
+
+  // get all lagr verts (departure vertices)
+  Range lagr_verts;
+  rval = mb->get_connectivity(localDepCells, lagr_verts);// they should be created in
+  // the same order as the euler vertices
+  int num_lagr_verts = (int) lagr_verts.size();
+  ERRORR(rval, "can't get local lagr vertices");
+
+  // now see the departure points position; to what boxes should we send them?
+  std::vector<double> dep_points(3 * num_lagr_verts);
+  rval = mb->get_coords(lagr_verts, &dep_points[0]);
+  ERRORR(rval, "can't get departure points position");
+  // ranges to send to each processor; will hold vertices and elements (quads?)
+  // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances)
+  std::map<int, Range> Rto;
+  int numprocs = parcomm->proc_config().proc_size();
+
+  for (Range::iterator eit = localDepCells.begin(); eit != localDepCells.end(); eit++)
+  {
+    EntityHandle q = *eit;
+    const EntityHandle * conn4;
+    int num_nodes;
+    rval = mb->get_connectivity(q, conn4, num_nodes);
+    ERRORR(rval, "can't get DP tag values");
+    CartVect qbmin(DBL_MAX);
+    CartVect qbmax(-DBL_MAX);
+    for (int i = 0; i < num_nodes; i++)
+    {
+      EntityHandle v = conn4[i];
+      int index = lagr_verts.index(v);
+      assert(-1!=index);
+      CartVect dp(&dep_points[3 * index]); // will use constructor
+      for (int j = 0; j < 3; j++)
+      {
+        if (qbmin[j] > dp[j])
+          qbmin[j] = dp[j];
+        if (qbmax[j] < dp[j])
+          qbmax[j] = dp[j];
+      }
+    }
+    for (int p = 0; p < numprocs; p++)
+    {
+      CartVect bbmin(&allBoxes[6 * p]);
+      CartVect bbmax(&allBoxes[6 * p + 3]);
+      if (GeomUtil::boxes_overlap(bbmin, bbmax, qbmin, qbmax, box_error))
+      {
+        Rto[p].insert(q);
+      }
+    }
+  }
+
+  // now, build TLv and TLq, for each p
+  size_t numq = 0;
+  size_t numv = 0;
+  for (int p = 0; p < numprocs; p++)
+  {
+    if (p == (int) my_rank)
+      continue; // do not "send" it, because it is already here
+    Range & range_to_P = Rto[p];
+    // add the vertices to it
+    if (range_to_P.empty())
+      continue; // nothing to send to proc p
+    Range vertsToP;
+    rval = mb->get_connectivity(range_to_P, vertsToP);
+    ERRORR(rval, "can't get connectivity");
+    numq = numq + range_to_P.size();
+    numv = numv + vertsToP.size();
+    range_to_P.merge(vertsToP);
+  }
+  TupleList TLv;
+  TupleList TLq;
+  TLv.initialize(2, 0, 0, 3, numv); // to proc, GLOBAL ID, DP points
+  TLv.enableWriteAccess();
+
+  int sizeTuple = 2 + max_edges; // max edges could be up to MAXEDGES :) for polygons
+  TLq.initialize(2+max_edges, 0, 1, 0, numq); // to proc, elem GLOBAL ID, connectivity[max_edges] (global ID v)
+  // send also the corresponding red cell it will come to
+  TLq.enableWriteAccess();
+  std::cout << "from proc " << my_rank << " send " << numv << " vertices and "
+      << numq << " elements\n";
+
+  for (int to_proc = 0; to_proc < numprocs; to_proc++)
+  {
+    if (to_proc == (int) my_rank)
+      continue;
+    Range & range_to_P = Rto[to_proc];
+    Range V = range_to_P.subset_by_type(MBVERTEX);
+
+    for (Range::iterator it = V.begin(); it != V.end(); it++)
+    {
+      EntityHandle v = *it;
+      int index = lagr_verts.index(v);// will be the same index as the corresponding vertex in euler verts
+      assert(-1!=index);
+      int n = TLv.get_n();
+      TLv.vi_wr[2 * n] = to_proc; // send to processor
+      TLv.vi_wr[2 * n + 1] = gids[index]; // global id needs index in the local_verts range
+      TLv.vr_wr[3 * n] = dep_points[3 * index]; // departure position, of the node local_verts[i]
+      TLv.vr_wr[3 * n + 1] = dep_points[3 * index + 1];
+      TLv.vr_wr[3 * n + 2] = dep_points[3 * index + 2];
+      TLv.inc_n();
+    }
+    // also, prep the 2d cells for sending ...
+    Range Q = range_to_P.subset_by_dimension(2);
+    for (Range::iterator it = Q.begin(); it != Q.end(); it++)
+    {
+      EntityHandle q = *it; // this is a blue cell
+      int global_id;
+      rval = mb->tag_get_data(gid, &q, 1, &global_id);
+      ERRORR(rval, "can't get gid for polygon");
+      int n = TLq.get_n();
+      TLq.vi_wr[sizeTuple * n] = to_proc; //
+      TLq.vi_wr[sizeTuple * n + 1] = global_id; // global id of element, used to identify it ...
+      const EntityHandle * conn4;
+      int num_nodes;
+      rval = mb->get_connectivity(q, conn4, num_nodes); // could be up to 10;
+      ERRORR(rval, "can't get connectivity for quad");
+      if (num_nodes > MAXEDGES)
+        ERRORR(MB_FAILURE, "too many nodes in a polygon");
+      for (int i = 0; i < num_nodes; i++)
+      {
+        EntityHandle v = conn4[i];
+        int index = lagr_verts.index(v);
+        assert(-1!=index);
+        TLq.vi_wr[sizeTuple * n + 2 + i] = gids[index];
+      }
+      for (int k = num_nodes; k < max_edges; k++)
+      {
+        TLq.vi_wr[sizeTuple * n + 2 + k] = 0; // fill the rest of node ids with 0; we know that the node ids start from 1!
+      }
+      EntityHandle redCell;
+      rval = mb->tag_get_data(corrTag, &q, 1, &redCell);
+      ERRORR(rval, "can't get corresponding red cell for dep cell");
+      TLq.vul_wr[n]=redCell; // this will be sent to remote_cells, to be able to come back
+      TLq.inc_n();
+
+    }
+
+  }
+  // now we can route them to each processor
+  // now we are done populating the tuples; route them to the appropriate processors
+  (parcomm->proc_config().crystal_router())->gs_transfer(1, TLv, 0);
+  (parcomm->proc_config().crystal_router())->gs_transfer(1, TLq, 0);
+  // the elements are already in localEnts;
+
+  // maps from global ids to new vertex and quad handles, that are added
+  std::map<int, EntityHandle> globalID_to_handle;
+  // we already have vertices from lagr set; they are already in the processor, even before receiving other
+  // verts from neighbors
+  int k=0;
+  for (Range::iterator vit=lagr_verts.begin(); vit!=lagr_verts.end(); vit++, k++)
+  {
+    globalID_to_handle[gids[k]] = *vit; // a little bit of overkill
+    // we do know that the global ids between euler and lagr verts are parallel
+  }
+  /*std::map<int, EntityHandle> globalID_to_eh;*/ // do we need this one?
+  globalID_to_eh.clear();
+  // now, look at every TLv, and see if we have to create a vertex there or not
+  int n = TLv.get_n(); // the size of the points received
+  for (int i = 0; i < n; i++)
+  {
+    int globalId = TLv.vi_rd[2 * i + 1];
+    if (globalID_to_handle.find(globalId) == globalID_to_handle.end())
+    {
+      EntityHandle new_vert;
+      double dp_pos[3] = { TLv.vr_wr[3 * i], TLv.vr_wr[3 * i + 1], TLv.vr_wr[3
+          * i + 2] };
+      rval = mb->create_vertex(dp_pos, new_vert);
+      ERRORR(rval, "can't create new vertex ");
+      globalID_to_handle[globalId] = new_vert;
+    }
+  }
+
+  // now, all dep points should be at their place
+  // look in the local list of 2d cells for this proc, and create all those cells if needed
+  // it may be an overkill, but because it does not involve communication, we do it anyway
+  Range & local = Rto[my_rank];
+  Range local_q = local.subset_by_dimension(2);
+  // the local should have all the vertices in lagr_verts
+  for (Range::iterator it = local_q.begin(); it != local_q.end(); it++)
+  {
+    EntityHandle q = *it;// these are from lagr cells, local
+    int gid_el;
+    rval = mb->tag_get_data(gid, &q, 1, &gid_el);
+    ERRORR(rval, "can't get element global ID ");
+    globalID_to_eh[gid_el] = q; // do we need this? maybe to just mark the ones on this processor
+    // maybe a range of global cell ids is fine?
+  }
+  // now look at all elements received through; we do not want to duplicate them
+  n = TLq.get_n(); // number of elements received by this processor
+  // a cell should be received from one proc only; so why are we so worried about duplicated elements?
+  // a vertex can be received from multiple sources, that is fine
+
+  remote_cells = new TupleList();
+  remote_cells->initialize(2, 0, 1, 1, n);
+  remote_cells->enableWriteAccess();
+  for (int i = 0; i < n; i++)
+  {
+    int globalIdEl = TLq.vi_rd[sizeTuple * i + 1];
+    int from_proc=TLq.vi_rd[sizeTuple * i ];
+    // do we already have a quad with this global ID, represented?
+    if (globalID_to_eh.find(globalIdEl) == globalID_to_eh.end())
+    {
+      // construct the conn quad
+      EntityHandle new_conn[MAXEDGES];
+      int nnodes;
+      for (int j = 0; j < max_edges; j++)
+      {
+        int vgid = TLq.vi_rd[sizeTuple * i + 2 + j]; // vertex global ID
+        if (vgid == 0)
+          new_conn[j] = 0;
+        else
+        {
+          assert(globalID_to_handle.find(vgid)!=globalID_to_handle.end());
+          new_conn[j] = globalID_to_handle[vgid];
+          nnodes = j + 1; // nodes are at the beginning, and are variable number
+        }
+      }
+      EntityHandle new_element;
+      //
+      EntityType entType = MBQUAD;
+      if (nnodes > 4)
+        entType = MBPOLYGON;
+      if (nnodes < 4)
+        entType = MBTRI;
+      rval = mb->create_element(entType, new_conn, nnodes, new_element);
+      ERRORR(rval, "can't create new element ");
+      globalID_to_eh[globalIdEl] = new_element;
+      local_q.insert(new_element);
+      rval = mb->tag_set_data(gid, &new_element, 1, &globalIdEl);
+      ERRORR(rval, "can't set gid on new element ");
+    }
+    remote_cells->vi_wr[2*i]=from_proc;
+    remote_cells->vi_wr[2*i+1]=globalIdEl;
+    remote_cells->vr_wr[i] = 0.; // no contribution yet sent back
+    remote_cells->vul_wr[i]= TLq.vul_rd[i];// this is the corresponding red cell (arrival)
+    remote_cells->inc_n();
+  }
+  // now, create a new set, covering_set
+  rval = mb->create_meshset(MESHSET_SET, covering_set);
+  ERRORR(rval, "can't create new mesh set ");
+  rval = mb->add_entities(covering_set, local_q);
+  ERRORR(rval, "can't add entities to new mesh set ");
+  // order the remote cells tuple list, with the global id, because we will search in it
+  //remote_cells->print("remote_cells before sorting");
+  moab::TupleList::buffer sort_buffer;
+  sort_buffer.buffer_init(n);
+  remote_cells->sort(1, &sort_buffer);
+  sort_buffer.reset();
+  return MB_SUCCESS;
+  //end copy
+}
 // this method will reduce number of nodes, collapse edges that are of length 0
   // so a polygon like 428 431 431 will become a line 428 431
   // or something like 428 431 431 531 -> 428 431 531

diff --git a/tools/mbcslam/Intx2Mesh.hpp b/tools/mbcslam/Intx2Mesh.hpp
index 21e56e4..6dcdc13 100644
--- a/tools/mbcslam/Intx2Mesh.hpp
+++ b/tools/mbcslam/Intx2Mesh.hpp
@@ -11,6 +11,7 @@
 #include <iostream>
 #include <sstream>
 #include <fstream>
+#include <map>
 #include <time.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -91,6 +92,17 @@ public:
 
   ErrorCode create_departure_mesh_2nd_alg(EntityHandle & euler_set, EntityHandle & covering_lagr_set);
 
+  // in this method, used in parallel, each departure elements are already created, and at their positions
+  // the covering_set is output, will contain the departure cells that cover the euler set; some of these
+  // departure cells might come from different processors
+  // so the covering_set contains some elements from lagr_set and some elements that come from other procs
+  // we need to keep track of what processors "sent" the elements so we know were to
+  // send back the info about the tracers masses
+
+  ErrorCode create_departure_mesh_3rd_alg(EntityHandle & lagr_set, EntityHandle & covering_set);
+
+  ErrorCode build_processor_euler_boxes(EntityHandle euler_set, Range & local_verts);
+
   void correct_polygon(EntityHandle * foundIds, int & nP);
 
   ErrorCode correct_intersection_points_positions();
@@ -145,10 +157,15 @@ protected: // so it can be accessed in derived classes, InPlane and OnSphere
   double box_error;
   /* \brief Local root of the kdtree */
   EntityHandle localRoot;
-  Range localEnts;// this range is for local elements of interest
+  Range localEnts;// this range is for local elements of interest, euler cells
 
   unsigned int my_rank;
 
+  int max_edges; // maximum number of edges in the euler set
+
+  TupleList * remote_cells;
+  std::map<int, EntityHandle> globalID_to_eh;// needed for parallel, mostly
+
 };
 
 } /* namespace moab */

diff --git a/tools/mbcslam/Intx2MeshOnSphere.cpp b/tools/mbcslam/Intx2MeshOnSphere.cpp
index 4ec7bcc..7ea5854 100644
--- a/tools/mbcslam/Intx2MeshOnSphere.cpp
+++ b/tools/mbcslam/Intx2MeshOnSphere.cpp
@@ -6,6 +6,8 @@
 
 #include "Intx2MeshOnSphere.hpp"
 #include "moab/GeomUtil.hpp"
+#include "MBTagConventions.hpp"
+#include "moab/ParallelComm.hpp"
 #include <queue>
 
 namespace moab {
@@ -416,14 +418,30 @@ bool Intx2MeshOnSphere::is_inside_element(double xyz[3], EntityHandle eh)
   return false;
 }
 
-ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagElem)
+ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagElem, Tag & tagArea)
 {
+  EntityHandle dum = 0;
+
+  Tag corrTag;
+  ErrorCode rval = mb->tag_get_handle(CORRTAGNAME,
+                                           1, MB_TYPE_HANDLE, corrTag,
+                                           MB_TAG_DENSE, &dum); // it should have been created
+  ERRORR(rval, "can't get correlation tag");
+
+  Tag gid;
+  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE);
+  ERRORR(rval,"can't get global ID tag" );
+
   // get all polygons out of out_set; then see where are they coming from
   Range polys;
-  ErrorCode rval = mb->get_entities_by_dimension(out_set, 2, polys);
+  rval = mb->get_entities_by_dimension(out_set, 2, polys);
   ERRORR(rval, "can't get polygons out");
 
-  // rs2 is the red rage, arrival; rs1 is blue, departure;
+  // rs2 is the red range, arrival; rs1 is blue, departure;
+  // there is a connection between rs1 and rs2, through the corrTag
+  // corrTag is __correlation
+  // basically, mb->tag_get_data(corrTag, &(redPoly), 1, &bluePoly);
+  // also,  mb->tag_get_data(corrTag, &(bluePoly), 1, &redPoly);
   // we start from rs2 existing, then we have to update something
   std::vector<double>  currentVals(rs2.size());
   rval = mb->tag_get_data(tagElem, rs2, &currentVals[0]);
@@ -440,25 +458,93 @@ ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagE
     int blueIndex, redIndex;
     rval =  mb->tag_get_data(blueParentTag, &poly, 1, &blueIndex);
     ERRORR(rval, "can't get blue tag");
-    //EntityHandle blue = rs1[blueIndex];
+    EntityHandle blue = rs1[blueIndex];
     rval =  mb->tag_get_data(redParentTag, &poly, 1, &redIndex);
     ERRORR(rval, "can't get red tag");
     //EntityHandle red = rs2[redIndex];
     // big assumption here, red and blue are "parallel" ;we should have an index from
     // blue to red (so a deformed blue corresponds to an arrival red)
     double areap = area_spherical_element(mb, poly, R);
-    newValues[blueIndex] += currentVals[redIndex]*areap;
+    // so the departure cell at time t (blueIndex) covers a portion of a redCell
+    // that quantity will be transported to the redCell at time t+dt
+    // the blue corresponds to a red arrival
+    EntityHandle redArr;
+    rval = mb->tag_get_data(corrTag, &blue, 1, &redArr);
+    if (0==redArr || MB_TAG_NOT_FOUND==rval)
+    {
+      if (!remote_cells)
+        ERRORR( MB_FAILURE, "no remote cells, failure\n");
+      // maybe the element is remote, from another processor
+      int global_id_blue;
+      rval = mb->tag_get_data(gid, &blue, 1, &global_id_blue);
+      ERRORR(rval, "can't get arrival red for corresponding blue gid");
+      // find the
+      int index_in_remote = remote_cells->find(1, global_id_blue);
+      if (index_in_remote==-1)
+        ERRORR( MB_FAILURE, "can't find the global id element in remote cells\n");
+      remote_cells->vr_wr[index_in_remote] += currentVals[redIndex]*areap;
+    }
+    else if (MB_SUCCESS==rval)
+    {
+      int arrRedIndex = rs2.index(redArr);
+      if (-1 == arrRedIndex)
+        ERRORR(MB_FAILURE, "can't find the red arrival index");
+      newValues[arrRedIndex] += currentVals[redIndex]*areap;
+    }
+
+    else
+      ERRORR(rval, "can't get arrival red for corresponding ");
   }
+  // now, send back the remote_cells to the processors they came from, with the updated values for
+  // the tracer mass in a cell
+  if (remote_cells)
+  {
+    // so this means that some cells will be sent back with tracer info to the procs they were sent from
+    (parcomm->proc_config().crystal_router())->gs_transfer(1, *remote_cells, 0);
+    // now, look at the global id, find the proper "red" cell with that index and update its mass
+    //remote_cells->print("remote cells after routing");
+    int n = remote_cells->get_n();
+    for (int j=0; j<n; j++)
+    {
+      EntityHandle redCell = remote_cells->vul_rd[j];// entity handle sent back
+      int arrRedIndex = rs2.index(redCell);
+      if (-1 == arrRedIndex)
+        ERRORR(MB_FAILURE, "can't find the red arrival index");
+      newValues[arrRedIndex] += remote_cells->vr_rd[j];
+    }
+  }
+
   // now divide by red area (current)
   int j=0;
-  for (Range::iterator it=rs2.begin(); it!=rs2.end(); it++, j++ )
+  Range::iterator iter = rs2.begin();
+  void * data=NULL; //used for stored area
+  int count =0;
+  double total_mass_local=0.;
+  while (iter != rs2.end())
   {
-    EntityHandle red = *it;
-    double areaRed = area_spherical_element(mb, red, R);
-    newValues[j]/=areaRed;
+    rval = mb->tag_iterate(tagArea, iter, rs2.end(), count, data);
+    ERRORR(rval, "can't tag iterate");
+    double * ptrArea=(double*)data;
+    for (int i=0; i<count; i++, iter++, j++, ptrArea++)
+    {
+      total_mass_local+=newValues[j];
+      newValues[j]/= (*ptrArea);
+    }
   }
   rval = mb->tag_set_data(tagElem, rs2, &newValues[0]);
   ERRORR(rval, "can't set new values tag");
+
+  double total_mass=0.;
+  int mpi_err = MPI_Reduce(&total_mass_local, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
+  if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
+  if (my_rank==0)
+    std::cout <<"total mass now:" << total_mass << "\n";
+
+  if (remote_cells)
+  {
+    delete remote_cells;
+    remote_cells=NULL;
+  }
   return MB_SUCCESS;
 }
 } /* namespace moab */

diff --git a/tools/mbcslam/Intx2MeshOnSphere.hpp b/tools/mbcslam/Intx2MeshOnSphere.hpp
index c2a3066..8047840 100644
--- a/tools/mbcslam/Intx2MeshOnSphere.hpp
+++ b/tools/mbcslam/Intx2MeshOnSphere.hpp
@@ -31,7 +31,7 @@ public:
 
   bool is_inside_element(double xyz[3], EntityHandle eh);
 
-  ErrorCode update_tracer_data(EntityHandle out_set, Tag & tagElem);
+  ErrorCode update_tracer_data(EntityHandle out_set, Tag & tagElem, Tag & tagArea);
 
 private:
   int plane; // current gnomonic plane

diff --git a/tools/mbcslam/Makefile.am b/tools/mbcslam/Makefile.am
index 440384c..b6b7b9d 100644
--- a/tools/mbcslam/Makefile.am
+++ b/tools/mbcslam/Makefile.am
@@ -15,7 +15,7 @@ AM_CPPFLAGS += -DSRCDIR=$(srcdir) \
                -I$(top_srcdir)/itaps/imesh \
                -I$(top_builddir)/itaps \
                -I$(top_builddir)/itaps/imesh \
-               -I$(top_srcdir)/test
+               -I$(top_srcdir)/test 
 
 lib_LTLIBRARIES = libmbcslam.la
 libmbcslam_la_LIBADD = $(top_builddir)/src/libMOAB.la $(top_builddir)/itaps/imesh/libiMesh.la \
@@ -40,7 +40,7 @@ cfgdir = $(libdir)
 
 TESTS = intx_on_sphere_test  intx_in_plane_test  spec_visu_test spherical_area_test \
          case1_test  intx_mpas
-noinst_PROGRAMS =  cslam_par_test diffusion proj1
+noinst_PROGRAMS =  cslam_par_test diffusion proj1 
 
 check_PROGRAMS = $(TESTS) 
 intx_on_sphere_test_SOURCES = intx_on_sphere_test.cpp

diff --git a/tools/mbcslam/diffusion.cpp b/tools/mbcslam/diffusion.cpp
index 6720c58..e6b3ad7 100644
--- a/tools/mbcslam/diffusion.cpp
+++ b/tools/mbcslam/diffusion.cpp
@@ -39,7 +39,6 @@ on the sphere; see CSLAM Utils case1
 
 #include "CslamUtils.hpp"
 
-
 // non smooth scalar field
 // some input data
 double gtol = 1.e-9; // this is for geometry tolerance
@@ -51,6 +50,9 @@ double T = 5;
 
 int case_number = 1; // 1, 2 (non-divergent) 3 divergent
 
+moab::Tag corrTag;
+bool noWrite = false;
+bool parallelWrite = false;
 int field_type = 1 ; // 1 quasi smooth, 2 - smooth, 3 non-smooth,
 #ifdef MESHDIR
 std::string TestDir( STRINGIFY(MESHDIR) );
@@ -166,7 +168,7 @@ ErrorCode add_field_value(Interface * mb, EntityHandle euler_set, int rank, Tag
 
 
   Range::iterator iter = polygons.begin();
-  double total_mass = 0.;
+  double local_mass = 0.; // this is total mass on one proc
   while (iter != polygons.end())
   {
     rval = mb->tag_iterate(tagElem, iter, polygons.end(), count, data);
@@ -202,18 +204,16 @@ ErrorCode add_field_value(Interface * mb, EntityHandle euler_set, int rank, Tag
 
       // we should have used some
       // total mass:
-      total_mass += *ptrArea * average;
+      local_mass += *ptrArea * average;
     }
 
   }
+  double total_mass=0.;
+  int mpi_err = MPI_Reduce(&local_mass, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
+  if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
 
-  std::stringstream iniPos;
-  iniPos<< "Tracer" << rank<<"_"<<0<<  ".vtk";// first time step
-
-  rval = mb->write_file(iniPos.str().c_str(), 0, 0, &euler_set, 1);
-  CHECK_ERR(rval);
-
-  std::cout << "initial total mass:" << total_mass << "\n";
+  if (rank==0)
+    std::cout << "initial total mass:" << total_mass << "\n";
 
   // now we can delete the tags? not yet
   return MB_SUCCESS;
@@ -260,21 +260,32 @@ ErrorCode compute_velocity_case1(Interface * mb, EntityHandle euler_set, Tag & t
     // increment to the next node
     ptr_velo+=3;// to next velocity
   }
-  std::stringstream velos;
-  velos<<"Tracer" << rank<<"_"<<tStep<<  ".vtk";
-  rval = mb->write_file(velos.str().c_str(), 0, 0, &euler_set, 1);
-  CHECK_ERR(rval);
+  if (!noWrite)
+  {
+    std::stringstream velos;
+    velos<<"Tracer" << rank<<"_"<<tStep<<  ".vtk";
+    rval = mb->write_file(velos.str().c_str(), 0, 0, &euler_set, 1, &tagh, 1);
+    CHECK_ERR(rval);
+  }
 
   return MB_SUCCESS;
 }
-ErrorCode compute_tracer_case1(Interface * mb, EntityHandle euler_set,
-    EntityHandle lagr_set, EntityHandle out_set,
-    Tag & tagElem, int rank, int tStep)
+ErrorCode  create_lagr_mesh(Interface * mb, EntityHandle euler_set, EntityHandle lagr_set)
 {
-  ErrorCode rval = MB_SUCCESS;
+  // create the handle tag for the corresponding element / vertex
+
+  EntityHandle dum = 0;
+
+  ErrorCode rval = mb->tag_get_handle(CORRTAGNAME,
+                                           1, MB_TYPE_HANDLE, corrTag,
+                                           MB_TAG_DENSE|MB_TAG_CREAT, &dum);
+  CHECK_ERR(rval);
+
+  // give the same global id to new verts and cells created in the lagr(departure) mesh
+  Tag gid;
+  rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE);
+  CHECK_ERR(rval);
 
-  double t = tStep*T/numSteps; // numSteps is global; so is T
-  double delta_t = T/numSteps; // this is global too, actually
   Range polys;
   rval = mb->get_entities_by_dimension(euler_set, 2, polys);
   CHECK_ERR(rval);
@@ -284,21 +295,29 @@ ErrorCode compute_tracer_case1(Interface * mb, EntityHandle euler_set,
   CHECK_ERR(rval);
 
   std::map<EntityHandle, EntityHandle> newNodes;
-  for (Range::iterator vit = connecVerts.begin(); vit != connecVerts.end();
-      vit++)
+  for (Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); vit++)
   {
     EntityHandle oldV = *vit;
     CartVect posi;
     rval = mb->get_coords(&oldV, 1, &(posi[0]));
     CHECK_ERR(rval);
-    // cslam utils, case 1
-    CartVect newPos;
-    departure_point_case1(posi, t, delta_t, newPos);
-    newPos = radius * newPos;
+    int global_id;
+    rval = mb->tag_get_data(gid, &oldV, 1, &global_id);
+    CHECK_ERR(rval);
     EntityHandle new_vert;
-    rval = mb->create_vertex(&(newPos[0]), new_vert);
+    rval = mb->create_vertex(&(posi[0]), new_vert); // duplicate the position
     CHECK_ERR(rval);
     newNodes[oldV] = new_vert;
+    // set also the correspondent tag :)
+    rval = mb->tag_set_data(corrTag, &oldV, 1, &new_vert);
+    CHECK_ERR(rval);
+    // also the other side
+    rval = mb->tag_set_data(corrTag, &new_vert, 1, &oldV);
+    CHECK_ERR(rval);
+    // set the global id
+    rval = mb->tag_set_data(gid, &new_vert, 1, &global_id);
+    CHECK_ERR(rval);
+
   }
   for (Range::iterator it = polys.begin(); it != polys.end(); it++)
   {
@@ -307,6 +326,9 @@ ErrorCode compute_tracer_case1(Interface * mb, EntityHandle euler_set,
     const EntityHandle * conn;
     rval = mb->get_connectivity(q, conn, nnodes);
     CHECK_ERR(rval);
+    int global_id;
+    rval = mb->tag_get_data(gid, &q, 1, &global_id);
+    CHECK_ERR(rval);
     EntityType typeElem = mb->type_from_handle(q);
     std::vector<EntityHandle> new_conn(nnodes);
     for (int i = 0; i < nnodes; i++)
@@ -317,37 +339,114 @@ ErrorCode compute_tracer_case1(Interface * mb, EntityHandle euler_set,
     EntityHandle newElement;
     rval = mb->create_element(typeElem, &new_conn[0], nnodes, newElement);
     CHECK_ERR(rval);
+    //set the corresponding tag
+    rval = mb->tag_set_data(corrTag, &q, 1, &newElement);
+    CHECK_ERR(rval);
+    rval = mb->tag_set_data(corrTag, &newElement, 1, &q);
+    CHECK_ERR(rval);
+    // set the global id
+    rval = mb->tag_set_data(gid, &newElement, 1, &global_id);
+    CHECK_ERR(rval);
+
     rval = mb->add_entities(lagr_set, &newElement, 1);
     CHECK_ERR(rval);
   }
+
+  return MB_SUCCESS;
+}
+ErrorCode compute_tracer_case1(Interface * mb, Intx2MeshOnSphere & worker, EntityHandle euler_set,
+    EntityHandle lagr_set, EntityHandle out_set, Tag & tagElem, Tag & tagArea, int rank,
+    int tStep, Range & connecVerts)
+{
+  ErrorCode rval = MB_SUCCESS;
+
+  if (!corrTag)
+    return MB_FAILURE;
+  double t = tStep * T / numSteps; // numSteps is global; so is T
+  double delta_t = T / numSteps; // this is global too, actually
+  Range polys;
+  rval = mb->get_entities_by_dimension(euler_set, 2, polys);
+  CHECK_ERR(rval);
+
+  // change coordinates of lagr mesh vertices
+  for (Range::iterator vit = connecVerts.begin(); vit != connecVerts.end();
+      vit++)
+  {
+    EntityHandle oldV = *vit;
+    CartVect posi;
+    rval = mb->get_coords(&oldV, 1, &(posi[0]));
+    CHECK_ERR(rval);
+    // cslam utils, case 1
+    CartVect newPos;
+    departure_point_case1(posi, t, delta_t, newPos);
+    newPos = radius * newPos; // do we need this? the radius should be 1
+    EntityHandle new_vert;
+    rval = mb->tag_get_data(corrTag, &oldV, 1, &new_vert);
+    CHECK_ERR(rval);
+    // set the new position for the new vertex
+    rval = mb->set_coords(&new_vert, 1, &(newPos[0]));
+    CHECK_ERR(rval);
+  }
+
+  // if in parallel, we have to move some elements to another proc, and receive other cells
+  // from other procs
+  // lagr and euler are preserved
+  EntityHandle covering_set;
+  rval = worker.create_departure_mesh_3rd_alg(lagr_set, covering_set);
+  if (!noWrite) // so if write
+  {
+    std::stringstream newTracer;
+    newTracer << "Tracer" << rank << "_" << tStep << ".vtk";
+    rval = mb->write_file(newTracer.str().c_str(), 0, 0, &euler_set, 1);
+
+    std::stringstream lagr_cover;
+    lagr_cover << "Cover" << rank << "_" << tStep << ".vtk";
+    rval = mb->write_file(lagr_cover.str().c_str(), 0, 0, &covering_set, 1);
+
+  }
   // so we have now the departure at the previous time
   // intersect the 2 meshes (what about some checking of convexity?) for sufficient
   // small dt, it is not an issue;
-  Intx2MeshOnSphere worker(mb);
-  worker.SetRadius(1.);
 
-  worker.SetErrorTolerance(gtol);
   // std::cout << "error tolerance epsilon_1=" << gtol << "\n";
 
-  rval = worker.intersect_meshes(lagr_set, euler_set, out_set);
+  rval = worker.intersect_meshes(covering_set, euler_set, out_set);
   CHECK_ERR(rval);
+  if (!noWrite) // so if write
+  {
+    std::stringstream intx_mesh;
+    intx_mesh << "Intx" << rank << "_" << tStep << ".vtk";
+    rval = mb->write_file(intx_mesh.str().c_str(), 0, 0, &out_set, 1);
+  }
+
   // serially: lagr is the same order as euler;
   // we need to update now the tracer information on each element, based on
   // initial value and areas of each resulting polygons
-  rval = worker.update_tracer_data(out_set, tagElem);
+  if (parallelWrite && tStep==1)
+  {
+    std::stringstream resTrace;
+    resTrace << "Tracer" << "_" << tStep-1 << ".h5m";
+    rval = mb->write_file(resTrace.str().c_str(), 0, "PARALLEL=WRITE_PART", &euler_set, 1, &tagElem, 1);
+  }
+  rval = worker.update_tracer_data(out_set, tagElem, tagArea);
   CHECK_ERR(rval);
 
-  std::stringstream newTracer;
-  newTracer<<"Tracer" << rank<<"_"<<tStep<<  ".vtk";
-  rval = mb->write_file(newTracer.str().c_str(), 0, 0, &euler_set, 1);
-  CHECK_ERR(rval);
+  if (parallelWrite)
+  {
+    std::stringstream resTrace;
+    resTrace << "Tracer" << "_" << tStep << ".h5m";
+    rval = mb->write_file(resTrace.str().c_str(), 0, "PARALLEL=WRITE_PART", &euler_set, 1, &tagElem, 1);
+  }
 
-  std::stringstream newIntx;
-  newIntx<<"newIntx" << rank<<"_"<<tStep<<  ".vtk";
-  rval = mb->write_file(newIntx.str().c_str(), 0, 0, &out_set, 1);
-  CHECK_ERR(rval);
-  // delete now the polygons and the lagr set ents
-  // also, all verts that are not in euler set
+  if (!noWrite) // so if write
+  {
+    std::stringstream newIntx;
+    newIntx << "newIntx" << rank << "_" << tStep << ".vtk";
+    rval = mb->write_file(newIntx.str().c_str(), 0, 0, &out_set, 1);
+    CHECK_ERR(rval);
+  }
+  // delete now the polygons and the elements of out_set
+  // also, all verts that are not in euler set or lagr_set
   Range allVerts;
   rval = mb->get_entities_by_dimension(0, 0, allVerts);
   CHECK_ERR(rval);
@@ -355,20 +454,28 @@ ErrorCode compute_tracer_case1(Interface * mb, EntityHandle euler_set,
   Range allElems;
   rval = mb->get_entities_by_dimension(0, 2, allElems);
   CHECK_ERR(rval);
-  Range todeleteVerts = subtract(allVerts, connecVerts);
+  // add to polys range the lagr polys
+  rval = mb->get_entities_by_dimension(lagr_set, 2, polys); // do not delete lagr set either, with its vertices
+  CHECK_ERR(rval);
+ // add to the connecVerts range all verts, from all initial polys
+  Range vertsToStay;
+  rval = mb->get_connectivity(polys, vertsToStay);
+  CHECK_ERR(rval);
+
+  Range todeleteVerts = subtract(allVerts, vertsToStay);
 
   Range todeleteElem = subtract(allElems, polys);
 
+  // empty the out mesh set
   rval = mb->clear_meshset(&out_set, 1);
   CHECK_ERR(rval);
 
-  rval = mb->clear_meshset(&lagr_set, 1);
-  CHECK_ERR(rval);
-
   rval = mb->delete_entities(todeleteElem);
   CHECK_ERR(rval);
   rval = mb->delete_entities(todeleteVerts);
   CHECK_ERR(rval);
+  if (rank==0)
+    std::cout << " step: " << tStep << "\n";
   return rval;
 }
 int main(int argc, char **argv)
@@ -409,11 +516,21 @@ int main(int argc, char **argv)
         numSteps = atoi(argv[++index]);
       }
 
+      if (!strcmp(argv[index], "-nw"))
+      {
+        noWrite = true;
+      }
+
+      if (!strcmp(argv[index], "-pw"))
+      {
+        parallelWrite = true;
+      }
+
       if (!strcmp(argv[index], "-h"))
       {
         std::cout << "usage: -gtol <tol> -input <file> -O <extra_read_opts> \n   "
         <<    "-f <field_type> -h (this help) -ns <numSteps> \n";
-        std::cout << " filed type: 1: quasi-smooth; 2: smooth; 3: slotted cylinders (non-smooth)\n";
+        std::cout << " field type: 1: quasi-smooth; 2: smooth; 3: slotted cylinders (non-smooth)\n";
         return 0;
       }
       index++;
@@ -463,11 +580,12 @@ int main(int argc, char **argv)
   rval = add_field_value(&mb, euler_set, rank, tagTracer, tagElem, tagArea);
   CHECK_ERR(rval);
 
-
-  // do some velocity fields at some time steps; with animations
-  // first delete the
-
-
+  Range redEls;
+  rval = mb.get_entities_by_dimension(euler_set, 2, redEls);
+  CHECK_ERR(rval);
+  std::vector<double> iniVals(redEls.size());
+  rval = mb.tag_get_data(tagElem, redEls, &iniVals[0]);
+  CHECK_ERR(rval);
 
   Tag tagh = 0;
   std::string tag_name3("Case1");
@@ -478,17 +596,67 @@ int main(int argc, char **argv)
   CHECK_ERR(rval);
   rval = mb.create_meshset(MESHSET_SET, lagr_set);
   CHECK_ERR(rval);
+  // copy the initial mesh in the lagrangian set
+  // initial vertices will be at the same position as euler;
+
+  rval = create_lagr_mesh(&mb, euler_set, lagr_set);
+  CHECK_ERR(rval);
+
+  Intx2MeshOnSphere worker(&mb);
+  worker.SetRadius(radius);
+
+  worker.SetErrorTolerance(gtol);
+
+  Range local_verts;
+  rval = worker.build_processor_euler_boxes(euler_set, local_verts);// output also the local_verts
+  // these stay fixed for one run
+  // other things from intersection might need to change, like input blue set (departure set)
+  // so we need also a method to clean memory
+  CHECK_ERR(rval);
+
   for (int i=1; i<numSteps+1; i++)
   {
     // time depends on i; t = i*T/numSteps: ( 0, T/numSteps, 2*T/numSteps, ..., T )
+    // this is really just to create some plots; it is not really needed to proceed
+    // the compute_tracer_case1 method actually computes the departure point position
     rval = compute_velocity_case1(&mb, euler_set, tagh, rank, i);
     CHECK_ERR(rval);
 
     // this is to actually compute concentrations, using the current concentrations
     //
-    rval = compute_tracer_case1(&mb, euler_set, lagr_set, out_set,
-        tagElem, rank, i);
+    rval = compute_tracer_case1(&mb, worker, euler_set, lagr_set, out_set,
+        tagElem, tagArea, rank, i, local_verts);
+    CHECK_ERR(rval);
 
   }
+
+  //final vals and 1-norm
+  Range::iterator iter = redEls.begin();
+  double norm1 = 0.;
+  int count =0;
+  void * data;
+  int j=0;// index in iniVals
+  while (iter != redEls.end())
+  {
+    rval = mb.tag_iterate(tagElem, iter, redEls.end(), count, data);
+    CHECK_ERR(rval);
+    double * ptrTracer=(double*)data;
+
+    rval = mb.tag_iterate(tagArea, iter, redEls.end(), count, data);
+    CHECK_ERR(rval);
+    double * ptrArea=(double*)data;
+    for (int i=0; i<count; i++, iter++, ptrTracer++, ptrArea++, j++)
+    {
+      //double area = *ptrArea;
+      norm1+=fabs(*ptrTracer - iniVals[j])* (*ptrArea);
+    }
+  }
+
+  double total_norm1=0;
+  int mpi_err = MPI_Reduce(&norm1, &total_norm1, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
+  if (MPI_SUCCESS != mpi_err) return 1;
+  if (0==rank)
+    std::cout << " numSteps:" << numSteps << " 1-norm:" << norm1 << "\n";
+  MPI_Finalize();
   return 0;
 }

diff --git a/tools/mbcslam/proj1.cpp b/tools/mbcslam/proj1.cpp
index e78ef79..7326b68 100644
--- a/tools/mbcslam/proj1.cpp
+++ b/tools/mbcslam/proj1.cpp
@@ -1,7 +1,8 @@
 /*
  * proj1.cpp
  *
- *  project on a sphere of radius R
+ *  project on a sphere of radius R, delete sets if needed, and delete edges between parts
+ *  (created by resolve shared ents)
  */
 
 #include "moab/Core.hpp"
@@ -18,8 +19,7 @@ double radius = 1.;// in m:  6371220.
 int main(int argc, char **argv)
 {
 
-  std::string extra_read_opts;
-  // read a file and project on a sphere
+  bool delete_partition_sets = false;
 
   if (argc < 3)
     return 1;
@@ -29,11 +29,20 @@ int main(int argc, char **argv)
   char * output = argv[2];
   while (index < argc)
   {
-    if (!strcmp(argv[index], "-R")) // this is for geometry tolerance
+    if (!strcmp(argv[index], "-R")) // this is for radius to project
     {
       radius = atof(argv[++index]);
     }
+    if (!strcmp(argv[index], "-DS")) // delete partition sets
+    {
+      delete_partition_sets = true;
+    }
 
+    if (!strcmp(argv[index], "-h"))
+    {
+      std::cout << " usage: proj1 <input><output> -R <value>  -DS (delete partition sets)\n";
+      return 1;
+    }
     index++;
   }
 
@@ -73,10 +82,38 @@ int main(int argc, char **argv)
   rval = mb.get_entities_by_dimension(0, 1, edges);
   if (MB_SUCCESS != rval)
     return 1;
+  // write edges to a new set, and after that, write the set, delete the edges and the set
+  EntityHandle sf1;
+  rval = mb.create_meshset(MESHSET_SET, sf1);
+  if (MB_SUCCESS != rval)
+    return 1;
+  rval = mb.add_entities(sf1, edges);
+  if (MB_SUCCESS != rval)
+    return 1;
+  rval = mb.write_mesh("edgesOnly.h5m", &sf1, 1);
+  if (MB_SUCCESS != rval)
+    return 1;
+  rval = mb.delete_entities(&sf1, 1);
+  if (MB_SUCCESS != rval)
+    return 1;
   mb.delete_entities(edges);
   mb.write_file(output);
 
-  // remove all edges
+  if (delete_partition_sets)
+  {
+    Tag par_tag;
+    rval = mb.tag_get_handle("PARALLEL_PARTITION", par_tag);
+    if (MB_SUCCESS == rval)
+
+    {
+      Range par_sets;
+      rval =  mb.get_entities_by_type_and_tag(0, MBENTITYSET, &par_tag, NULL, 1, par_sets,
+         moab::Interface::UNION);
+      if (!par_sets.empty())
+        mb.delete_entities(par_sets);
+      mb.tag_delete(par_tag);
+    }
+  }
 
 
   return 0;

diff --git a/tools/mbzoltan/mbpart.cpp b/tools/mbzoltan/mbpart.cpp
index 7ad6dd2..c7a6c50 100644
--- a/tools/mbzoltan/mbpart.cpp
+++ b/tools/mbzoltan/mbpart.cpp
@@ -112,6 +112,10 @@ int main(int argc, char* argv[])
   bool print_time = false;
   opts.addOpt<void>(",T", "Print CPU time for each phase.", &print_time);
 
+  bool spherical_coords = false;
+  opts.addOpt<void>("project_on_sphere,s",
+      "use spherical coordinates for partitioning ", &spherical_coords);
+
   opts.parseCommandLine(argc, argv);
 
   MBZoltan *tool = NULL;
@@ -263,7 +267,7 @@ int main(int argc, char* argv[])
         zoltan_method.c_str(),
         (!parm_method.empty() ? parm_method.c_str() : oct_method.c_str()),
         imbal_tol, !no_write_sets, write_tags, part_dim, obj_weight,
-        edge_weight, part_surf, ghost, print_time);
+        edge_weight, part_surf, ghost, print_time, spherical_coords);
     if (MB_SUCCESS != rval)
     {
       std::cerr << "Partitioner failed!" << std::endl;


https://bitbucket.org/fathomteam/moab/commits/2b75bc7c928e/
Changeset:   2b75bc7c928e
Branch:      None
User:        danwu
Date:        2013-11-15 16:26:22
Summary:     Merged fathomteam/moab into master
Affected #:  17 files

diff --git a/src/Core.cpp b/src/Core.cpp
index ad6bdda..a6e6cfd 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -2971,7 +2971,7 @@ ErrorCode Core::side_number(const EntityHandle parent,
     return (0 == temp_result ? MB_SUCCESS : MB_FAILURE);
   }
   else if (TYPE_FROM_HANDLE(parent) == MBPOLYGON) {
-      // find location of 1st vertex
+      // find location of 1st vertex; this works even for padded vertices
     const EntityHandle *first_v = std::find(parent_conn, parent_conn+num_parent_vertices,
                                               child_conn[0]);
     if (first_v == parent_conn+num_parent_vertices) return MB_ENTITY_NOT_FOUND;
@@ -2990,11 +2990,23 @@ ErrorCode Core::side_number(const EntityHandle parent,
       else return MB_ENTITY_NOT_FOUND;
     }
     else if (TYPE_FROM_HANDLE(child) == MBEDGE) {
+      // determine the actual number of vertices, for the padded case
+      // the padded case could be like ABCDEFFF; num_parent_vertices=8, actual_num_parent_vertices=6
+      int actual_num_parent_vertices = num_parent_vertices;
+      while(actual_num_parent_vertices>=3 &&
+          (parent_conn[actual_num_parent_vertices-2] ==parent_conn[actual_num_parent_vertices-1] ) )
+        actual_num_parent_vertices--;
+
       if (parent_conn[(sd_number+1)%num_parent_vertices] == child_conn[1])
         sense = 1;
       else if (parent_conn[(sd_number+num_parent_vertices-1)%num_parent_vertices] ==
-               child_conn[1])
+               child_conn[1]) // this will also cover edge AF for padded case, side will be 0, sense -1
         sense = -1;
+      // if edge FA in above example, we should return sd_number = 5, sense 1
+      else if ((sd_number==actual_num_parent_vertices-1) && (child_conn[1]==parent_conn[0]))
+        sense =1;
+      else
+        return MB_ENTITY_NOT_FOUND;
       return MB_SUCCESS;
     }
   }

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index bc8da0f..ebf149c 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -10,10 +10,10 @@
 #include "MBTagConventions.hpp"
 
 #define ERRORR(rval, str) \
-    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+  if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
 
 #define ERRORS(err, str) \
-    if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
+  if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
 
 namespace moab {
 
@@ -304,9 +304,88 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
   return MB_SUCCESS;
 }
 
+ErrorCode NCHelper::read_variable_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
+                                        std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
+  std::map<std::string, ReadNC::VarData>::iterator mit;
+
+  // If empty read them all
+  if (var_names.empty()) {
+    for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
+      ReadNC::VarData vd = (*mit).second;
+
+      // No need to read ignored variables. Upon creation of dummy variables,
+      // tag values have already been set
+      if (ignoredVarNames.find(vd.varName) != ignoredVarNames.end() ||
+          dummyVarNames.find(vd.varName) != dummyVarNames.end())
+         continue;
+
+      if (vd.entLoc == ReadNC::ENTLOCSET)
+        vsetdatas.push_back(vd);
+      else
+        vdatas.push_back(vd);
+    }
+  }
+  else {
+    for (unsigned int i = 0; i < var_names.size(); i++) {
+      mit = varInfo.find(var_names[i]);
+      if (mit != varInfo.end()) {
+        ReadNC::VarData vd = (*mit).second;
+
+        // No need to read ignored variables. Upon creation of dummy variables,
+        // tag values have already been set
+        if (ignoredVarNames.find(vd.varName) != ignoredVarNames.end() ||
+            dummyVarNames.find(vd.varName) != dummyVarNames.end())
+           continue;
+
+        if (vd.entLoc == ReadNC::ENTLOCSET)
+          vsetdatas.push_back(vd);
+        else
+          vdatas.push_back(vd);
+      }
+      else {
+        ERRORR(MB_FAILURE, "Couldn't find variable.");
+      }
+    }
+  }
+
+  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()) {
+    for (unsigned int i = 0; i < vdatas.size(); i++) {
+      vdatas[i].varTags.resize(tstep_nums.size(), 0);
+      vdatas[i].varDatas.resize(tstep_nums.size());
+      vdatas[i].readStarts.resize(tstep_nums.size());
+      vdatas[i].readCounts.resize(tstep_nums.size());
+    }
+
+    for (unsigned int i = 0; i < vsetdatas.size(); i++) {
+      if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
+          && (vsetdatas[i].varDims.size() != 1)) {
+        vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
+        vsetdatas[i].varDatas.resize(tstep_nums.size());
+        vsetdatas[i].readStarts.resize(tstep_nums.size());
+        vsetdatas[i].readCounts.resize(tstep_nums.size());
+      }
+      else {
+        vsetdatas[i].varTags.resize(1, 0);
+        vsetdatas[i].varDatas.resize(1);
+        vsetdatas[i].readStarts.resize(1);
+        vsetdatas[i].readCounts.resize(1);
+      }
+    }
+  }
+
+  return MB_SUCCESS;
+}
+
 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;
   DebugOutput& dbgOut = _readNC->dbgOut;
 
@@ -316,11 +395,6 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
   // Finally, read into that space
   int success;
   for (unsigned int i = 0; i < vdatas.size(); i++) {
-    // This is a dummy variable for a dimension with no corresponding coordinate variable
-    // No need to set its tag data
-    if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end())
-       continue;
-
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
       void* data = vdatas[i].varDatas[t];
 
@@ -367,7 +441,7 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
       rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
       ERRORR(rval, "Failed to set data for variable.");
 
-      if (vdatas[i].varDims.size() <= 1)
+      if (vdatas[i].varDims.size() <= 1 || !vdatas[i].has_t)
         break;
     }
   }
@@ -643,56 +717,63 @@ ErrorCode NCHelper::create_attrib_string(const std::map<std::string, ReadNC::Att
   return MB_SUCCESS;
 }
 
-void NCHelper::init_dims_with_no_coord_vars_info()
+ErrorCode NCHelper::create_dummy_variables()
 {
+  Interface*& mbImpl = _readNC->mbImpl;
   std::vector<std::string>& dimNames = _readNC->dimNames;
-  std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
+  std::vector<int>& dimLens = _readNC->dimLens;
   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 from unstructured meshes, such as ncol(HOMME) and nCells(MPAS)
-  // For them, create dummy tags
+  // Right now, candidates are from unstructured meshes, such as ncol (HOMME) and nCells (MPAS)
+  // For each of them, create a dummy variable with a sparse tag to store the dimension length
   for (unsigned int i = 0; i < dimNames.size(); i++) {
-    // If there is a variable with this dimension name, skip, we are fine; if not, create a dummy varInfo
+    // If there is a variable with this dimension name, skip
     if (varInfo.find(dimNames[i]) != varInfo.end())
       continue;
 
+    // Create a dummy variable
     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.varDataType = NC_INT;
     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]);
+    dbgOut.tprintf(2, "Dummy variable created for dimension %s\n", dimNames[i].c_str());
+
+    // Create a sparse tag to store the dimension length
+    Tag tagh;
+    ErrorCode rval = mbImpl->tag_get_handle(dimNames[i].c_str(), 1, MB_TYPE_INTEGER, tagh,
+                                            MB_TAG_SPARSE | MB_TAG_CREAT | MB_TAG_EXCL);
+    // If the tag already exists, skip
+    if (MB_ALREADY_ALLOCATED == rval)
+      continue;
+    ERRORR(rval, "Failed to create dimension tag.");
+
+    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &dimLens[i]);
+    ERRORR(rval, "Failed to set data for dimension tag.");
+
+    dbgOut.tprintf(2, "Sparse tag created for dimension %s\n", dimNames[i].c_str());
   }
+
+  return MB_SUCCESS;
 }
 
 ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
 {
-  std::set<std::string>& dummyVarNames = _readNC->dummyVarNames;
   std::vector<int>& dimLens = _readNC->dimLens;
   DebugOutput& dbgOut = _readNC->dbgOut;
 
   ErrorCode rval = MB_SUCCESS;
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
-    // This is a dummy variable for a dimension with no corresponding coordinate variable
-    // No need to allocate memory to read it
-    if (dummyVarNames.find(vdatas[i].varName) != dummyVarNames.end()) {
-      if (!vdatas[i].varTags[0]) {
-        rval = get_tag_to_set(vdatas[i], 0, vdatas[i].varTags[0]);
-        ERRORR(rval, "Trouble getting dummy tag.");
-      }
-      continue;
-    }
-
     if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim) != vdatas[i].varDims.end()))
       vdatas[i].has_t = true;
 
@@ -761,7 +842,7 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
           rval = MB_FAILURE;
       }
 
-      if (vdatas[i].varDims.size() <= 1)
+      if (vdatas[i].varDims.size() <= 1 || !vdatas[i].has_t)
         break;
     }
   }
@@ -790,14 +871,14 @@ ErrorCode ScdNCHelper::check_existing_mesh() {
 
   // Check the number of elements too
   int num_elems;
-  rval = mbImpl->get_number_entities_by_dimension(_fileSet, (-1 == lDims[2] ? 2 : 3), num_elems);
+  rval = mbImpl->get_number_entities_by_dimension(_fileSet, (-1 == lCDims[2] ? 2 : 3), num_elems);
   ERRORR(rval, "Trouble getting number of elements.");
 
   /*
   // Check against parameters
-  // The expected number of elements calculated below is incorrect (to be updated later)
+  // When ghosting is used, this check might fail (to be updated later)
   if (num_elems > 0) {
-    int expected_elems = (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]) * (-1 == lDims[2] ? 1 : lDims[5] - lDims[2]);
+    int expected_elems = (lCDims[3] - lCDims[0] + 1) * (lCDims[4] - lCDims[1] + 1) * (-1 == lCDims[2] ? 1 : (lCDims[5] - lCDims[2] + 1));
     if (num_elems != expected_elems) {
       ERRORR(MB_FAILURE, "Number of elements doesn't match.");
     }
@@ -817,7 +898,7 @@ ErrorCode ScdNCHelper::create_mesh(Range& faces)
   ScdParData& parData = _readNC->parData;
 
   Range tmp_range;
-  ScdBox *scd_box;
+  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, true);
@@ -913,7 +994,7 @@ ErrorCode ScdNCHelper::read_variables(std::vector<std::string>& var_names, std::
   std::vector<ReadNC::VarData> vdatas;
   std::vector<ReadNC::VarData> vsetdatas;
 
-  ErrorCode rval = read_scd_variable_setup(var_names, tstep_nums, vdatas, vsetdatas);
+  ErrorCode rval = read_variable_setup(var_names, tstep_nums, vdatas, vsetdatas);
   ERRORR(rval, "Trouble setting up read variable.");
 
   // Create COORDS tag for quads
@@ -933,83 +1014,6 @@ ErrorCode ScdNCHelper::read_variables(std::vector<std::string>& var_names, std::
   return MB_SUCCESS;
 }
 
-ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
-                                               std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
-{
-  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
-  std::map<std::string, ReadNC::VarData>::iterator mit;
-
-  // If empty read them all
-  if (var_names.empty()) {
-    for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
-      ReadNC::VarData vd = (*mit).second;
-      if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-          vd.varDims.end(), jCDim) != vd.varDims.end()))
-        vdatas.push_back(vd);
-      else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-         vd.varDims.end(), iCDim) != vd.varDims.end()))
-        vdatas.push_back(vd);
-      else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-          vd.varDims.end(), iDim) != vd.varDims.end()))
-        vdatas.push_back(vd);
-      else
-        vsetdatas.push_back(vd);
-    }
-  }
-  else {
-    for (unsigned int i = 0; i < var_names.size(); i++) {
-      mit = varInfo.find(var_names[i]);
-      if (mit != varInfo.end()) {
-        ReadNC::VarData vd = (*mit).second;
-        if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-           vd.varDims.end(), jCDim) != vd.varDims.end()))
-          vdatas.push_back(vd);
-        else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-            vd.varDims.end(), iCDim) != vd.varDims.end()))
-          vdatas.push_back(vd);
-        else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-            vd.varDims.end(), iDim) != vd.varDims.end()))
-          vdatas.push_back(vd);
-        else
-          vsetdatas.push_back(vd);
-      }
-      else ERRORR(MB_FAILURE, "Couldn't find variable.");
-    }
-  }
-
-  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()) {
-    for (unsigned int i = 0; i < vdatas.size(); i++) {
-      vdatas[i].varTags.resize(tstep_nums.size(), 0);
-      vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readStarts.resize(tstep_nums.size());
-      vdatas[i].readCounts.resize(tstep_nums.size());
-    }
-
-    for (unsigned int i = 0; i < vsetdatas.size(); i++) {
-      if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
-          && (vsetdatas[i].varDims.size() != 1)) {
-        vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
-        vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readStarts.resize(tstep_nums.size());
-        vsetdatas[i].readCounts.resize(tstep_nums.size());
-      }
-      else {
-        vsetdatas[i].varTags.resize(1, 0);
-        vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readStarts.resize(1);
-        vsetdatas[i].readCounts.resize(1);
-      }
-    }
-  }
-
-  return MB_SUCCESS;
-}
-
 ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
 {
   Interface*& mbImpl = _readNC->mbImpl;
@@ -1051,8 +1055,6 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
 #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]);
 
@@ -1075,17 +1077,14 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
       vdatas[i].readStarts[t].push_back(tstep_nums[t]);
       vdatas[i].readCounts[t].push_back(1);
 
-      // Next: numLev
-      if (vdatas[i].numLev != 1) {
-        vdatas[i].readStarts[t].push_back(0);
-        vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-      }
+      // Next: numLev, even if it is 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
           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]);
@@ -1102,8 +1101,8 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
         case ReadNC::ENTLOCFACE:
           // 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);
+          vdatas[i].readStarts[t].push_back(lCDims[0]);
           vdatas[i].readCounts[t].push_back(lCDims[3] - lCDims[0] + 1);
           assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
 #ifdef USE_MPI
@@ -1246,6 +1245,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
         rval = tmp_rval;
     }
   }
+
   // Debug output, if requested
   if (1 == dbgOut.get_verbosity()) {
     dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
@@ -1322,7 +1322,7 @@ ErrorCode UcdNCHelper::read_variables(std::vector<std::string>& var_names, std::
   std::vector<ReadNC::VarData> vdatas;
   std::vector<ReadNC::VarData> vsetdatas;
 
-  ErrorCode rval = read_ucd_variable_setup(var_names, tstep_nums, vdatas, vsetdatas);
+  ErrorCode rval = read_variable_setup(var_names, tstep_nums, vdatas, vsetdatas);
   ERRORR(rval, "Trouble setting up read variable.");
 
   if (!vsetdatas.empty()) {

diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index f3d1875..817257c 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -36,7 +36,13 @@ public:
   ErrorCode create_conventional_tags(const std::vector<int>& tstep_nums);
 
 protected:
-  //! Read set variables, common to scd mesh and ucd mesh
+  //! Separate set and non-set variables (common to scd mesh and ucd mesh)
+  ErrorCode read_variable_setup(std::vector<std::string>& var_names,
+                                            std::vector<int>& tstep_nums,
+                                            std::vector<ReadNC::VarData>& vdatas,
+                                            std::vector<ReadNC::VarData>& vsetdatas);
+
+  //! Read set variables (common to scd mesh and ucd mesh)
   ErrorCode read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums);
 
   //! Convert variables in place
@@ -49,18 +55,18 @@ protected:
 
   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'
+  //! 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
+  //! 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);
 
-  //! Initialize information for dimensions that don't have corresponding
-  //! coordinate variables - this information is used for creating dummy tags
-  void init_dims_with_no_coord_vars_info();
+  //! For a dimension that does not have a corresponding coordinate variable (e.g. ncol for HOMME),
+  //! create a dummy variable with a sparse tag to store the dimension length
+  ErrorCode create_dummy_variables();
 
 private:
   //! Used by read_variable_to_set()
@@ -83,6 +89,12 @@ protected:
 
   //! Dimension numbers for time and level
   int tDim, levDim;
+
+  //! Ignored variables
+  std::set<std::string> ignoredVarNames;
+
+  //! Dummy variables
+  std::set<std::string> dummyVarNames;
 };
 
 //! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
@@ -113,12 +125,6 @@ private:
   //! Implementation of NCHelper::read_variables()
   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,
-                                    std::vector<int>& tstep_nums,
-                                    std::vector<ReadNC::VarData>& vdatas,
-                                    std::vector<ReadNC::VarData>& vsetdatas);
-
   //! Read non-set variables for scd mesh
   ErrorCode read_scd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
                                                  std::vector<int>& tstep_nums);
@@ -187,12 +193,6 @@ private:
   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)
-  virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_names,
-                                            std::vector<int>& tstep_nums,
-                                            std::vector<ReadNC::VarData>& vdatas,
-                                            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(std::vector<ReadNC::VarData>& vdatas,
                                                          std::vector<int>& tstep_nums) = 0;

diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index 48056c6..b117921 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -6,10 +6,10 @@
 #include <sstream>
 
 #define ERRORR(rval, str) \
-    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+  if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
 
 #define ERRORS(err, str) \
-    if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
+  if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAILURE;}
 
 namespace moab {
 
@@ -319,13 +319,21 @@ ErrorCode NCHelperEuler::init_mesh_vals()
   dbgOut.tprintf(1, "%d elements, %d vertices\n", (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]), (lDims[3] - lDims[0] + 1)
       * (lDims[4] - lDims[1] + 1));
 
-  // Determine the entity location type of a variable
+  // For each variable, determine the entity location type and number of levels
   std::map<std::string, ReadNC::VarData>::iterator mit;
   for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
     ReadNC::VarData& vd = (*mit).second;
-    if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-        vd.varDims.end(), jCDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCFACE;
+
+    vd.entLoc = ReadNC::ENTLOCSET;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) {
+      if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) &&
+          (std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()))
+        vd.entLoc = ReadNC::ENTLOCFACE;
+    }
+
+    vd.numLev = 1;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end())
+      vd.numLev = nLevels;
   }
 
   // For Eul models, slon and slat are "virtual" dimensions (not defined in the file header)
@@ -451,8 +459,9 @@ ErrorCode NCHelperEuler::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // Hack: create dummy tags, if needed, for dimensions with no corresponding coordinate variables
-  init_dims_with_no_coord_vars_info();
+  // Hack: create dummy variables, if needed, for dimensions with no corresponding coordinate variables
+  rval = create_dummy_variables();
+  ERRORR(rval, "Failed to create dummy variables.");
 
   return MB_SUCCESS;
 }

diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 253d598..7725b55 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -6,7 +6,7 @@
 #include <sstream>
 
 #define ERRORR(rval, str) \
-    if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
+ if (MB_SUCCESS != rval) {_readNC->readMeshIface->report_error("%s", str); return rval;}
 
 namespace moab {
 
@@ -315,19 +315,27 @@ ErrorCode NCHelperFV::init_mesh_vals()
   dbgOut.tprintf(1, "%d elements, %d vertices\n", (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]), (lDims[3] - lDims[0] + 1)
       * (lDims[4] - lDims[1] + 1));
 
-  // Determine the entity location type of a variable
+  // For each variable, determine the entity location type and number of levels
   std::map<std::string, ReadNC::VarData>::iterator mit;
   for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
     ReadNC::VarData& vd = (*mit).second;
-    if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-        vd.varDims.end(), jCDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCFACE;
-    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-        vd.varDims.end(), iCDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCNSEDGE;
-    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-        vd.varDims.end(), iDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCEWEDGE;
+
+    vd.entLoc = ReadNC::ENTLOCSET;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) {
+      if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()) &&
+          (std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()))
+        vd.entLoc = ReadNC::ENTLOCFACE;
+      else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) != vd.varDims.end()) &&
+          (std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) != vd.varDims.end()))
+        vd.entLoc = ReadNC::ENTLOCNSEDGE;
+      else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) != vd.varDims.end()) &&
+          (std::find(vd.varDims.begin(), vd.varDims.end(), iDim) != vd.varDims.end()))
+        vd.entLoc = ReadNC::ENTLOCEWEDGE;
+    }
+
+    vd.numLev = 1;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end())
+      vd.numLev = nLevels;
   }
 
   std::vector<std::string> ijdimNames(4);
@@ -452,8 +460,9 @@ ErrorCode NCHelperFV::init_mesh_vals()
       dbgOut.tprintf(2, "Tag created for variable %s\n", tag_name.c_str());
   }
 
-  // Hack: create dummy tags, if needed, for dimensions with no corresponding coordinate variables
-  init_dims_with_no_coord_vars_info();
+  // Hack: create dummy variables, if needed, for dimensions with no corresponding coordinate variables
+  rval = create_dummy_variables();
+  ERRORR(rval, "Failed to create dummy variables.");
 
   return MB_SUCCESS;
 }

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 154d61d..25c4441 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -151,17 +151,25 @@ ErrorCode NCHelperHOMME::init_mesh_vals()
       tVals.push_back((double)t);
   }
 
-  // Determine the entity location type of a variable
+  // For each variable, determine the entity location type and number of levels
   std::map<std::string, ReadNC::VarData>::iterator mit;
   for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
     ReadNC::VarData& vd = (*mit).second;
-    if ((std::find(vd.varDims.begin(), vd.varDims.end(), vDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-        vd.varDims.end(), levDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCVERT;
+
+    vd.entLoc = ReadNC::ENTLOCSET;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) {
+      if (std::find(vd.varDims.begin(), vd.varDims.end(), vDim) != vd.varDims.end())
+        vd.entLoc = ReadNC::ENTLOCVERT;
+    }
+
+    vd.numLev = 1;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end())
+      vd.numLev = nLevels;
   }
 
-  // Hack: create dummy tags for dimensions (like ncol) with no corresponding coordinate variables
-  init_dims_with_no_coord_vars_info();
+  // Hack: create dummy variables for dimensions (like ncol) with no corresponding coordinate variables
+  rval = create_dummy_variables();
+  ERRORR(rval, "Failed to create dummy variables.");
 
   return MB_SUCCESS;
 }
@@ -499,76 +507,6 @@ ErrorCode NCHelperHOMME::create_mesh(Range& faces)
   return MB_SUCCESS;
 }
 
-ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
-                                                 std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
-{
-  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
-  std::map<std::string, ReadNC::VarData>::iterator mit;
-
-  // If empty read them all
-  if (var_names.empty()) {
-    for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
-      ReadNC::VarData vd = (*mit).second;
-      if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-          vd.varDims.end(), levDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), vDim)
-          != vd.varDims.end()))
-        vdatas.push_back(vd); // 3D data (time, lev, ncol) read here
-      else
-        vsetdatas.push_back(vd);
-    }
-  }
-  else {
-    for (unsigned int i = 0; i < var_names.size(); i++) {
-      mit = varInfo.find(var_names[i]);
-      if (mit != varInfo.end()) {
-        ReadNC::VarData vd = (*mit).second;
-        if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-            vd.varDims.end(), levDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), vDim)
-            != vd.varDims.end()))
-          vdatas.push_back(vd); // 3D data (time, lev, ncol) read here
-        else
-          vsetdatas.push_back(vd);
-      }
-      else {
-        ERRORR(MB_FAILURE, "Couldn't find variable.");
-      }
-    }
-  }
-
-  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()) {
-    for (unsigned int i = 0; i < vdatas.size(); i++) {
-      vdatas[i].varTags.resize(tstep_nums.size(), 0);
-      vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readStarts.resize(tstep_nums.size());
-      vdatas[i].readCounts.resize(tstep_nums.size());
-    }
-
-    for (unsigned int i = 0; i < vsetdatas.size(); i++) {
-      if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
-          && (vsetdatas[i].varDims.size() != 1)) {
-        vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
-        vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readStarts.resize(tstep_nums.size());
-        vsetdatas[i].readCounts.resize(tstep_nums.size());
-      }
-      else {
-        vsetdatas[i].varTags.resize(1, 0);
-        vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readStarts.resize(1);
-        vsetdatas[i].readCounts.resize(1);
-      }
-    }
-  }
-
-  return MB_SUCCESS;
-}
-
 ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
 {
   Interface*& mbImpl = _readNC->mbImpl;
@@ -610,11 +548,9 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC
       vdatas[i].readStarts[t].push_back(tstep_nums[t]);
       vdatas[i].readCounts[t].push_back(1);
 
-      // Next: numLev
-      if (vdatas[i].numLev != 1) {
-        vdatas[i].readStarts[t].push_back(0);
-        vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-      }
+      // Next: numLev, even if it is 1
+      vdatas[i].readStarts[t].push_back(0);
+      vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
 
       // Finally: nVertices
       switch (vdatas[i].entLoc) {

diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index d064469..82ba90e 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -33,11 +33,6 @@ private:
   //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_allocate()
   virtual ErrorCode read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
                                                          std::vector<int>& tstep_nums);
-  //! Implementation of UcdNCHelper::read_ucd_variable_setup()
-  virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_names,
-                                            std::vector<int>& tstep_nums,
-                                            std::vector<ReadNC::VarData>& vdatas,
-                                            std::vector<ReadNC::VarData>& vsetdatas);
 #ifdef PNETCDF_FILE
   //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_async()
   virtual ErrorCode read_ucd_variable_to_nonset_async(std::vector<ReadNC::VarData>& vdatas,

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 54ba598..c803bf3 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -26,6 +26,22 @@ NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& opts,
 , numCellGroups(0)
 , createGatherSet(false)
 {
+  // Ignore variables containing topological information
+  ignoredVarNames.insert("nEdgesOnEdge");
+  ignoredVarNames.insert("nEdgesOnCell");
+  ignoredVarNames.insert("edgesOnVertex");
+  ignoredVarNames.insert("cellsOnVertex");
+  ignoredVarNames.insert("verticesOnEdge");
+  ignoredVarNames.insert("edgesOnEdge");
+  ignoredVarNames.insert("cellsOnEdge");
+  ignoredVarNames.insert("verticesOnCell");
+  ignoredVarNames.insert("edgesOnCell");
+  ignoredVarNames.insert("cellsOnCell");
+
+  // Ignore variables for index conversion
+  ignoredVarNames.insert("indexToVertexID");
+  ignoredVarNames.insert("indexToEdgeID");
+  ignoredVarNames.insert("indexToCellID");
 }
 
 bool NCHelperMPAS::can_read_file(ReadNC* readNC)
@@ -97,7 +113,7 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
   vDim = idx;
   nVertices = dimLens[idx];
 
-  // Get number of levels
+  // Get number of vertex levels
   if ((vit = std::find(dimNames.begin(), dimNames.end(), "nVertLevels")) != dimNames.end())
     idx = vit - dimNames.begin();
   else {
@@ -106,6 +122,27 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
   levDim = idx;
   nLevels = dimLens[idx];
 
+  // Dimension numbers for other optional levels
+  std::vector<unsigned int> opt_lev_dims;
+
+  // Get number of vertex levels P1
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "nVertLevelsP1")) != dimNames.end()) {
+    idx = vit - dimNames.begin();
+    opt_lev_dims.push_back(idx);
+  }
+
+  // Get number of vertex levels P2
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "nVertLevelsP2")) != dimNames.end()) {
+    idx = vit - dimNames.begin();
+    opt_lev_dims.push_back(idx);
+  }
+
+  // Get number of soil levels
+  if ((vit = std::find(dimNames.begin(), dimNames.end(), "nSoilLevels")) != dimNames.end()) {
+    idx = vit - dimNames.begin();
+    opt_lev_dims.push_back(idx);
+  }
+
   std::map<std::string, ReadNC::VarData>::iterator vmit;
 
   // Store time coordinate values in tVals
@@ -121,22 +158,41 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
     }
   }
 
-  // Determine the entity location type of a variable
+  // For each variable, determine the entity location type and number of levels
   for (vmit = varInfo.begin(); vmit != varInfo.end(); ++vmit) {
     ReadNC::VarData& vd = (*vmit).second;
-    if ((std::find(vd.varDims.begin(), vd.varDims.end(), vDim) != vd.varDims.end()) &&
-      (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCVERT;
-    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), eDim) != vd.varDims.end()) &&
-      (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCEDGE;
-    else if ((std::find(vd.varDims.begin(), vd.varDims.end(), cDim) != vd.varDims.end()) &&
-      (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end()))
-      vd.entLoc = ReadNC::ENTLOCFACE;
+
+    vd.entLoc = ReadNC::ENTLOCSET;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) {
+      if (std::find(vd.varDims.begin(), vd.varDims.end(), vDim) != vd.varDims.end())
+        vd.entLoc = ReadNC::ENTLOCVERT;
+      else if (std::find(vd.varDims.begin(), vd.varDims.end(), eDim) != vd.varDims.end())
+        vd.entLoc = ReadNC::ENTLOCEDGE;
+      else if (std::find(vd.varDims.begin(), vd.varDims.end(), cDim) != vd.varDims.end())
+        vd.entLoc = ReadNC::ENTLOCFACE;
+    }
+
+    vd.numLev = 1;
+    if (std::find(vd.varDims.begin(), vd.varDims.end(), levDim) != vd.varDims.end())
+      vd.numLev = nLevels;
+    else {
+      // If nVertLevels dimension is not found, try other optional levels such as nVertLevelsP1
+      for (unsigned int i = 0; i < opt_lev_dims.size(); i++) {
+        if (std::find(vd.varDims.begin(), vd.varDims.end(), opt_lev_dims[i]) != vd.varDims.end()) {
+          vd.numLev = dimLens[opt_lev_dims[i]];
+          break;
+        }
+      }
+    }
+
+    // Hack: ignore variables with more than 3 dimensions, e.g. tracers(Time, nCells, nVertLevels, nTracers)
+    if (vd.varDims.size() > 3)
+      ignoredVarNames.insert(vd.varName);
   }
 
-  // Hack: create dummy tags for dimensions (like nCells) with no corresponding coordinate variables
-  init_dims_with_no_coord_vars_info();
+  // Hack: create dummy variables for dimensions (like nCells) with no corresponding coordinate variables
+  rval = create_dummy_variables();
+  ERRORR(rval, "Failed to create dummy variables.");
 
   return MB_SUCCESS;
 }
@@ -449,96 +505,6 @@ ErrorCode NCHelperMPAS::create_mesh(Range& faces)
   return MB_SUCCESS;
 }
 
-ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& var_names, std::vector<int>& tstep_nums,
-                                                 std::vector<ReadNC::VarData>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
-{
-  std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
-  std::map<std::string, ReadNC::VarData>::iterator mit;
-
-  // If empty read them all
-  if (var_names.empty()) {
-    for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
-      ReadNC::VarData vd = (*mit).second;
-      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()))
-          vdatas.push_back(vd); // 3D data (Time, nCells, nVertLevels) read here
-        else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-            vd.varDims.end(), eDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), levDim)
-            != vd.varDims.end()))
-          vdatas.push_back(vd); // 3D data (Time, nEdges, nVertLevels) read here
-        else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-            vd.varDims.end(), vDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), levDim)
-            != vd.varDims.end()))
-          vdatas.push_back(vd); // 3D data (Time, nVertices, nVertLevels) read here
-      }
-      else if (1 == vd.varDims.size())
-        vsetdatas.push_back(vd);
-    }
-  }
-  else {
-    for (unsigned int i = 0; i < var_names.size(); i++) {
-      mit = varInfo.find(var_names[i]);
-      if (mit != varInfo.end()) {
-        ReadNC::VarData vd = (*mit).second;
-        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()))
-            vdatas.push_back(vd); // 3D data (Time, nCells, nVertLevels) read here
-          else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-              vd.varDims.end(), eDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), levDim)
-              != vd.varDims.end()))
-            vdatas.push_back(vd); // 3D data (Time, nEdges, nVertLevels) read here
-          else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(),
-              vd.varDims.end(), vDim) != vd.varDims.end()) && (std::find(vd.varDims.begin(), vd.varDims.end(), levDim)
-              != vd.varDims.end()))
-            vdatas.push_back(vd); // 3D data (Time, nVertices, nVertLevels) read here
-        }
-        else if (1 == vd.varDims.size())
-          vsetdatas.push_back(vd);
-      }
-      else {
-        ERRORR(MB_FAILURE, "Couldn't find variable.");
-      }
-    }
-  }
-
-  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()) {
-    for (unsigned int i = 0; i < vdatas.size(); i++) {
-      vdatas[i].varTags.resize(tstep_nums.size(), 0);
-      vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readStarts.resize(tstep_nums.size());
-      vdatas[i].readCounts.resize(tstep_nums.size());
-    }
-
-    for (unsigned int i = 0; i < vsetdatas.size(); i++) {
-      if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
-          && (vsetdatas[i].varDims.size() != 1)) {
-        vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
-        vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readStarts.resize(tstep_nums.size());
-        vsetdatas[i].readCounts.resize(tstep_nums.size());
-      }
-      else {
-        vsetdatas[i].varTags.resize(1, 0);
-        vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readStarts.resize(1);
-        vsetdatas[i].readCounts.resize(1);
-      }
-    }
-  }
-
-  return MB_SUCCESS;
-}
-
 ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
 {
   Interface*& mbImpl = _readNC->mbImpl;
@@ -585,8 +551,6 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
     if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
       continue;
 
-    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]);
       // Get the tag to read into
@@ -636,7 +600,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
       // Last, numLev, even if it is 1
       vdatas[i].readStarts[t].push_back(0);
       vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-      assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
+      // Some variables have no level dimension, e.g. surface_pressure(Time, nCells)
+      assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size() ||
+             vdatas[i].readStarts[t].size() == vdatas[i].varDims.size() + 1);
 
       // Get ptr to tag space
       if (vdatas[i].entLoc == ReadNC::ENTLOCFACE && numCellGroups > 1) {

diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
index 0f053bc..6c6dc99 100644
--- a/src/io/NCHelperMPAS.hpp
+++ b/src/io/NCHelperMPAS.hpp
@@ -33,11 +33,6 @@ private:
   //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_allocate()
   virtual ErrorCode read_ucd_variable_to_nonset_allocate(std::vector<ReadNC::VarData>& vdatas,
                                                          std::vector<int>& tstep_nums);
-  //! Implementation of UcdNCHelper::read_ucd_variable_setup()
-  virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_names,
-                                            std::vector<int>& tstep_nums,
-                                            std::vector<ReadNC::VarData>& vdatas,
-                                            std::vector<ReadNC::VarData>& vsetdatas);
 #ifdef PNETCDF_FILE
   //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_async()
   virtual ErrorCode read_ucd_variable_to_nonset_async(std::vector<ReadNC::VarData>& vdatas,

diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index e930930..a0e02b4 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -132,16 +132,16 @@ ErrorCode ReadNC::load_file(const char* file_name, const EntityHandle* file_set,
       return rval;
   }
   else {
-    // Read dimension variable by default, the ones that are also variables
-    std::vector<std::string> filteredDimNames;
+    // Read dimension variables by default (the dimensions that are also variables)
+    std::vector<std::string> dim_var_names;
     for (unsigned int i = 0; i < dimNames.size(); i++) {
       std::map<std::string, VarData>::iterator mit = varInfo.find(dimNames[i]);
       if (mit != varInfo.end())
-        filteredDimNames.push_back(dimNames[i]);
+        dim_var_names.push_back(dimNames[i]);
     }
 
-    if (!filteredDimNames.empty()) {
-      rval = myHelper->read_variables(filteredDimNames, tstep_nums);
+    if (!dim_var_names.empty()) {
+      rval = myHelper->read_variables(dim_var_names, tstep_nums);
       if (MB_FAILURE == rval)
         return rval;
     }
@@ -302,7 +302,7 @@ ErrorCode ReadNC::read_header()
   ERRORR(result, "Getting attributes.");
   dbgOut.tprintf(1, "Read %u attributes\n", (unsigned int) globalAtts.size());
 
-  // Read in dimensions into dimVals
+  // Read in dimensions into dimNames and dimLens
   result = get_dimensions(fileId, dimNames, dimLens);
   ERRORR(result, "Getting dimensions.");
   dbgOut.tprintf(1, "Read %u dimensions\n", (unsigned int) dimNames.size());

diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index fc75140..c452716 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -165,9 +165,6 @@ private:
   //! Dimension lengths
   std::vector<int> dimLens;
 
-  //! These should be taken out when we fix the dummy var info things
-  std::set<std::string> dummyVarNames;
-
   //! Global attribs
   std::map<std::string, AttData> globalAtts;
 

diff --git a/test/parallel/parallel_unit_tests.cpp b/test/parallel/parallel_unit_tests.cpp
index 45ef1c5..85cc3b8 100644
--- a/test/parallel/parallel_unit_tests.cpp
+++ b/test/parallel/parallel_unit_tests.cpp
@@ -1447,8 +1447,10 @@ template <typename T> ErrorCode check_shared_ents(ParallelComm &pcomm, Tag tagh,
     if (1 == np && shprocs[0] != (int) pcomm.proc_config().proc_rank()) np++;
     if      (mpi_op == MPI_SUM) {if (dum_vals[i] != fact*np) return MB_FAILURE;}
     else if (mpi_op == MPI_PROD) {if (dum_vals[i] != pow(fact, np)) return MB_FAILURE;}
-    else if (mpi_op == MPI_MAX) {if (dum_vals[i] != fact) return MB_FAILURE;}
-    else if (mpi_op == MPI_MIN) {if (dum_vals[i] != fact) return MB_FAILURE;}
+    else if (mpi_op == MPI_MAX) {if (pcomm.rank() && std::find(&shprocs[0],&shprocs[np], 0) != &shprocs[np] &&
+                                     dum_vals[i] != fact) return MB_FAILURE;}
+    else if (mpi_op == MPI_MIN) {if (pcomm.rank() && std::find(&shprocs[0],&shprocs[np], 0) != &shprocs[np] &&
+                                     dum_vals[i] != fact) return MB_FAILURE;}
     else return MB_FAILURE;
   }
   

diff --git a/test/parallel/scdtest.cpp b/test/parallel/scdtest.cpp
index 3202621..5338b81 100644
--- a/test/parallel/scdtest.cpp
+++ b/test/parallel/scdtest.cpp
@@ -49,6 +49,7 @@ int main(int argc, char *argv[])
   MPI_Comm_size(MPI_COMM_WORLD, &size);
   if (size != 4 && size != 2) {
     cerr << "Run this with 2 or 4 processes\n";
+    MPI_Finalize();
     exit(1);
   }
 

diff --git a/tools/mbcslam/Intx2MeshOnSphere.cpp b/tools/mbcslam/Intx2MeshOnSphere.cpp
index 7ea5854..a1d786b 100644
--- a/tools/mbcslam/Intx2MeshOnSphere.cpp
+++ b/tools/mbcslam/Intx2MeshOnSphere.cpp
@@ -452,6 +452,7 @@ ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagE
   std::vector<double> newValues(rs2.size(), 0.);// initialize with 0 all of them
   // area of the polygon * conc on red (old) current quantity
   // finaly, divide by the area of the red
+  double check_intx_area=0.;
   for (Range::iterator it= polys.begin(); it!=polys.end(); it++)
   {
     EntityHandle poly=*it;
@@ -465,6 +466,7 @@ ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagE
     // big assumption here, red and blue are "parallel" ;we should have an index from
     // blue to red (so a deformed blue corresponds to an arrival red)
     double areap = area_spherical_element(mb, poly, R);
+    check_intx_area+=areap;
     // so the departure cell at time t (blueIndex) covers a portion of a redCell
     // that quantity will be transported to the redCell at time t+dt
     // the blue corresponds to a red arrival
@@ -535,10 +537,17 @@ ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagE
   ERRORR(rval, "can't set new values tag");
 
   double total_mass=0.;
+  double total_intx_area =0;
   int mpi_err = MPI_Reduce(&total_mass_local, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
   if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
+  // now reduce total area
+  mpi_err = MPI_Reduce(&check_intx_area, &total_intx_area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
+  if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
   if (my_rank==0)
+  {
     std::cout <<"total mass now:" << total_mass << "\n";
+    std::cout <<"check: total intersection area: (4 * M_PI * R^2): " << total_intx_area << "\n";
+  }
 
   if (remote_cells)
   {

diff --git a/tools/mbcslam/diffusion.cpp b/tools/mbcslam/diffusion.cpp
index e6b3ad7..378473e 100644
--- a/tools/mbcslam/diffusion.cpp
+++ b/tools/mbcslam/diffusion.cpp
@@ -39,6 +39,10 @@ on the sphere; see CSLAM Utils case1
 
 #include "CslamUtils.hpp"
 
+const char BRIEF_DESC[] =
+    "Simulate a transport problem in a semi-Lagrangian formulation\n";
+std::ostringstream LONG_DESC;
+
 // non smooth scalar field
 // some input data
 double gtol = 1.e-9; // this is for geometry tolerance
@@ -51,8 +55,9 @@ double T = 5;
 int case_number = 1; // 1, 2 (non-divergent) 3 divergent
 
 moab::Tag corrTag;
-bool noWrite = false;
+bool writeFiles = false;
 bool parallelWrite = false;
+bool velocity = false;
 int field_type = 1 ; // 1 quasi smooth, 2 - smooth, 3 non-smooth,
 #ifdef MESHDIR
 std::string TestDir( STRINGIFY(MESHDIR) );
@@ -260,13 +265,12 @@ ErrorCode compute_velocity_case1(Interface * mb, EntityHandle euler_set, Tag & t
     // increment to the next node
     ptr_velo+=3;// to next velocity
   }
-  if (!noWrite)
-  {
-    std::stringstream velos;
-    velos<<"Tracer" << rank<<"_"<<tStep<<  ".vtk";
-    rval = mb->write_file(velos.str().c_str(), 0, 0, &euler_set, 1, &tagh, 1);
-    CHECK_ERR(rval);
-  }
+
+  std::stringstream velos;
+  velos<<"Tracer" << rank<<"_"<<tStep<<  ".vtk";
+  rval = mb->write_file(velos.str().c_str(), 0, 0, &euler_set, 1, &tagh, 1);
+  CHECK_ERR(rval);
+
 
   return MB_SUCCESS;
 }
@@ -312,9 +316,11 @@ ErrorCode  create_lagr_mesh(Interface * mb, EntityHandle euler_set, EntityHandle
     rval = mb->tag_set_data(corrTag, &oldV, 1, &new_vert);
     CHECK_ERR(rval);
     // also the other side
-    rval = mb->tag_set_data(corrTag, &new_vert, 1, &oldV);
-    CHECK_ERR(rval);
-    // set the global id
+    // need to check if we really need this; the new vertex will never need the old vertex
+    // we have the global id which is the same
+    /*rval = mb->tag_set_data(corrTag, &new_vert, 1, &oldV);
+    CHECK_ERR(rval);*/
+    // set the global id on the corresponding vertex the same as the initial vertex
     rval = mb->tag_set_data(gid, &new_vert, 1, &global_id);
     CHECK_ERR(rval);
 
@@ -339,9 +345,9 @@ ErrorCode  create_lagr_mesh(Interface * mb, EntityHandle euler_set, EntityHandle
     EntityHandle newElement;
     rval = mb->create_element(typeElem, &new_conn[0], nnodes, newElement);
     CHECK_ERR(rval);
-    //set the corresponding tag
-    rval = mb->tag_set_data(corrTag, &q, 1, &newElement);
-    CHECK_ERR(rval);
+    //set the corresponding tag; not sure we need this one, from old to new
+    /*rval = mb->tag_set_data(corrTag, &q, 1, &newElement);
+    CHECK_ERR(rval);*/
     rval = mb->tag_set_data(corrTag, &newElement, 1, &q);
     CHECK_ERR(rval);
     // set the global id
@@ -393,7 +399,7 @@ ErrorCode compute_tracer_case1(Interface * mb, Intx2MeshOnSphere & worker, Entit
   // lagr and euler are preserved
   EntityHandle covering_set;
   rval = worker.create_departure_mesh_3rd_alg(lagr_set, covering_set);
-  if (!noWrite) // so if write
+  if (writeFiles) // so if write
   {
     std::stringstream newTracer;
     newTracer << "Tracer" << rank << "_" << tStep << ".vtk";
@@ -412,7 +418,7 @@ ErrorCode compute_tracer_case1(Interface * mb, Intx2MeshOnSphere & worker, Entit
 
   rval = worker.intersect_meshes(covering_set, euler_set, out_set);
   CHECK_ERR(rval);
-  if (!noWrite) // so if write
+  if (writeFiles) // so if write
   {
     std::stringstream intx_mesh;
     intx_mesh << "Intx" << rank << "_" << tStep << ".vtk";
@@ -438,7 +444,7 @@ ErrorCode compute_tracer_case1(Interface * mb, Intx2MeshOnSphere & worker, Entit
     rval = mb->write_file(resTrace.str().c_str(), 0, "PARALLEL=WRITE_PART", &euler_set, 1, &tagElem, 1);
   }
 
-  if (!noWrite) // so if write
+  if (writeFiles) // so if write
   {
     std::stringstream newIntx;
     newIntx << "newIntx" << rank << "_" << tStep << ".vtk";
@@ -482,62 +488,49 @@ int main(int argc, char **argv)
 {
 
   MPI_Init(&argc, &argv);
+  LONG_DESC << "This program simulates a transport problem on a sphere"
+        " according to a benchmark from a Nair & Lauritzen paper.\n"
+        << "It starts with a partitioned mesh on a sphere, add a tracer, and steps through.\n" <<
+        "The flow reverses after half time, and it should return to original configuration, if the integration was exact. ";
+  ProgOptions opts(LONG_DESC.str(), BRIEF_DESC);
 
-  std::string extra_read_opts;
   // read a homme file, partitioned in 16 so far
   std::string fileN= TestDir + "/HN16.h5m";
   const char *filename_mesh1 = fileN.c_str();
-  if (argc > 1)
-  {
-    int index = 1;
-    while (index < argc)
-    {
-      if (!strcmp(argv[index], "-gtol")) // this is for geometry tolerance
-      {
-        gtol = atof(argv[++index]);
-      }
-
-      if (!strcmp(argv[index], "-input"))
-      {
-        filename_mesh1 = argv[++index];
-      }
-
-      if (!strcmp(argv[index], "-O"))
-      {
-        extra_read_opts = std::string(argv[++index]);
-      }
-
-      if (!strcmp(argv[index], "-f"))
-      {
-        field_type = atoi(argv[++index]);
-      }
-      if (!strcmp(argv[index], "-ns"))
-      {
-        numSteps = atoi(argv[++index]);
-      }
-
-      if (!strcmp(argv[index], "-nw"))
-      {
-        noWrite = true;
-      }
-
-      if (!strcmp(argv[index], "-pw"))
-      {
-        parallelWrite = true;
-      }
-
-      if (!strcmp(argv[index], "-h"))
-      {
-        std::cout << "usage: -gtol <tol> -input <file> -O <extra_read_opts> \n   "
-        <<    "-f <field_type> -h (this help) -ns <numSteps> \n";
-        std::cout << " field type: 1: quasi-smooth; 2: smooth; 3: slotted cylinders (non-smooth)\n";
-        return 0;
-      }
-      index++;
-    }
-  }
-  // start copy
-  std::string opts = std::string("PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION")+
+
+  opts.addOpt<double>("gtolerance,g",
+      "geometric absolute tolerance (used for point concidence on the sphere)", &gtol);
+
+  std::string input_file;
+  opts.addOpt<std::string>("input_file,i", "input mesh file, partitioned",
+      &input_file);
+  std::string extra_read_opts;
+  opts.addOpt<std::string>("extra_read_options,O", "extra read options ",
+        &extra_read_opts);
+  //int field_type;
+  opts.addOpt<int>("field_type,f",
+        "field type--  1: quasi-smooth; 2: smooth; 3: slotted cylinders (non-smooth)", &field_type);
+
+  opts.addOpt<int>("num_steps,n",
+          "number of  steps ", &numSteps);
+
+  //bool reorder = false;
+  opts.addOpt<void>("write_debug_files,w", "write debugging files during simulation ",
+        &writeFiles);
+
+  opts.addOpt<void>("write_velocity_files,v", "Reorder mesh to group entities by partition",
+     &velocity);
+
+  opts.addOpt<void>("write_result_in_parallel,p", "write tracer result files",
+     &parallelWrite);
+
+  opts.parseCommandLine(argc, argv);
+
+  if (!input_file.empty())
+    filename_mesh1=input_file.c_str();
+
+  // read in parallel, in the "euler_set", the initial mesh
+  std::string optsRead = std::string("PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION")+
             std::string(";PARALLEL_RESOLVE_SHARED_ENTS")+extra_read_opts;
   Core moab;
   Interface & mb = moab;
@@ -546,31 +539,40 @@ int main(int argc, char **argv)
   rval = mb.create_meshset(MESHSET_SET, euler_set);
   CHECK_ERR(rval);
 
-  rval = mb.load_file(filename_mesh1, &euler_set, opts.c_str());
+  rval = mb.load_file(filename_mesh1, &euler_set, optsRead.c_str());
 
   ParallelComm* pcomm = ParallelComm::get_pcomm(&mb, 0);
   CHECK_ERR(rval);
 
   rval = pcomm->check_all_shared_handles();
   CHECK_ERR(rval);
-  // end copy
+
   int rank = pcomm->proc_config().proc_rank();
 
   if (0==rank)
+  {
     std::cout << " case 1: use -gtol " << gtol <<
         " -R " << radius << " -input " << filename_mesh1 <<  " -f " << field_type <<
         " numSteps: " << numSteps << "\n";
+    std::cout<<" write debug results: " << (writeFiles ? "yes" : "no") << "\n";
+    std::cout<< " write tracer in parallel: " << ( parallelWrite ? "yes" : "no") << "\n";
+    std::cout <<" output velocity: " << (velocity? "yes" : "no") << "\n";
+  }
 
+  // tagTracer is the value at nodes
   Tag tagTracer = 0;
   std::string tag_name("Tracer");
   rval = mb.tag_get_handle(tag_name.c_str(), 1, MB_TYPE_DOUBLE, tagTracer, MB_TAG_DENSE | MB_TAG_CREAT);
   CHECK_ERR(rval);
 
+  // tagElem is the average computed at each element, from nodal values
   Tag tagElem = 0;
   std::string tag_name2("TracerAverage");
   rval = mb.tag_get_handle(tag_name2.c_str(), 1, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT);
   CHECK_ERR(rval);
 
+  // area of the euler element is fixed, store it; it is used to recompute the averages at each
+  // time step
   Tag tagArea = 0;
   std::string tag_name4("Area");
   rval = mb.tag_get_handle(tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT);
@@ -580,6 +582,7 @@ int main(int argc, char **argv)
   rval = add_field_value(&mb, euler_set, rank, tagTracer, tagElem, tagArea);
   CHECK_ERR(rval);
 
+  // iniVals are used for 1-norm error computation
   Range redEls;
   rval = mb.get_entities_by_dimension(euler_set, 2, redEls);
   CHECK_ERR(rval);
@@ -619,10 +622,14 @@ int main(int argc, char **argv)
     // time depends on i; t = i*T/numSteps: ( 0, T/numSteps, 2*T/numSteps, ..., T )
     // this is really just to create some plots; it is not really needed to proceed
     // the compute_tracer_case1 method actually computes the departure point position
-    rval = compute_velocity_case1(&mb, euler_set, tagh, rank, i);
-    CHECK_ERR(rval);
+    if (velocity)
+    {
+      rval = compute_velocity_case1(&mb, euler_set, tagh, rank, i);
+      CHECK_ERR(rval);
+    }
 
-    // this is to actually compute concentrations, using the current concentrations
+    // this is to actually compute concentrations at time step i, using the
+    //  current concentrations
     //
     rval = compute_tracer_case1(&mb, worker, euler_set, lagr_set, out_set,
         tagElem, tagArea, rank, i, local_verts);
@@ -656,7 +663,7 @@ int main(int argc, char **argv)
   int mpi_err = MPI_Reduce(&norm1, &total_norm1, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
   if (MPI_SUCCESS != mpi_err) return 1;
   if (0==rank)
-    std::cout << " numSteps:" << numSteps << " 1-norm:" << norm1 << "\n";
+    std::cout << " numSteps:" << numSteps << " 1-norm:" << total_norm1 << "\n";
   MPI_Finalize();
   return 0;
 }

diff --git a/tools/mbcslam/intx_mpas.cpp b/tools/mbcslam/intx_mpas.cpp
index 6888cb3..570c97f 100644
--- a/tools/mbcslam/intx_mpas.cpp
+++ b/tools/mbcslam/intx_mpas.cpp
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
   MPI_Init(&argc, &argv);
 
   std::string extra_read_opts;
-  std::string fileN= TestDir + "/mpas_p8.h5m";
+  std::string fileN= TestDir + "/io/mpasx1.642.t.2.nc";
   const char *filename_mesh1 = fileN.c_str();
   bool flux_form = false;
   if (argc > 1)
@@ -164,8 +164,8 @@ int main(int argc, char **argv)
     }
   }
   // start copy
-  std::string opts = std::string("PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION")+
-            std::string(";PARALLEL_RESOLVE_SHARED_ENTS")+extra_read_opts;
+  std::string opts = std::string("PARALLEL=READ_PART;PARTITION_METHOD=RCBZOLTAN")+
+            std::string(";PARALLEL_RESOLVE_SHARED_ENTS;VARIABLE=;")+extra_read_opts;
   Core moab;
   Interface & mb = moab;
   EntityHandle euler_set;

diff --git a/tools/mbzoltan/mbpart.cpp b/tools/mbzoltan/mbpart.cpp
index c7a6c50..0dcabac 100644
--- a/tools/mbzoltan/mbpart.cpp
+++ b/tools/mbzoltan/mbpart.cpp
@@ -90,7 +90,7 @@ int main(int argc, char* argv[])
 
   bool ghost = false;
   long num_parts;
-  opts.addOpt<void>("ghost,h", "Specify if partition ghost geometry body.");
+  opts.addOpt<void>("ghost,H", "Specify if partition ghost geometry body.");
 
   int obj_weight = 0;
   opts.addOpt<int>("vertex_w,v",


https://bitbucket.org/fathomteam/moab/commits/ab38251ac54d/
Changeset:   ab38251ac54d
Branch:      None
User:        danwu
Date:        2013-11-19 18:53:38
Summary:     Merged fathomteam/moab into master
Affected #:  9 files

diff --git a/.gitignore b/.gitignore
index d3721c3..4e0534c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ examples/itaps/TagIterateC
 examples/itaps/TagIterateF
 examples/KDTree
 examples/ObbTree
+examples/PushParMeshIntoMoabF90
 examples/ReduceExchangeTags
 examples/SetsNTags
 examples/SkinMesh

diff --git a/examples/PushParMeshIntoMoabF90.F90 b/examples/PushParMeshIntoMoabF90.F90
new file mode 100644
index 0000000..131d19c
--- /dev/null
+++ b/examples/PushParMeshIntoMoabF90.F90
@@ -0,0 +1,281 @@
+! PushParMeshIntoMoabF90: push parallel mesh into moab, F90 version
+! 
+! This program shows how to push a mesh into MOAB in parallel from Fortran90, with sufficient
+! information to resolve boundary sharing and exchange a layer of ghost information.
+! To successfully link this example, you need to specify FCFLAGS that include:
+!    a) -DUSE_MPI, and
+!    b) flags required to link Fortran90 MPI programs with the C++ compiler; these flags
+!       can often be found on your system by inspecting the output of 'mpif90 -show'
+! For example, using gcc, the link line looks like:
+!   make MOAB_DIR=<moab install dir> FCFLAGS="-DUSE_MPI -I/usr/lib/openmpi/include -pthread -I/usr/lib/openmpi/lib -L/usr/lib/openmpi/lib -lmpi_f90 -lmpi_f77 -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl" PushParMeshIntoMoabF90
+!
+! Usage: PushParMeshIntoMoab
+
+program PushParMeshIntoMoab
+
+  use ISO_C_BINDING
+  implicit none
+
+#ifdef USE_MPI
+#  include "iMeshP_f.h"
+#else
+#  include "iMesh_f.h"
+#endif
+
+  ! declarations
+  ! imesh is the instance handle
+  iMesh_Instance imesh
+  ! NUMV, NUME, NVPERE are the hardwired here; these are for the whole mesh,
+  ! local mesh determined later
+  integer NUMV, NUME, NVPERE
+  parameter (NUMV = 8)   ! # vertices in whole mesh
+  parameter (NUME = 6)   ! # elements in whole mesh
+  parameter (NVPERE = 4) ! # vertices per element
+  ! ents, verts will be arrays storing vertex/entity handles
+  iBase_EntityHandle, pointer :: ents, verts
+  iBase_EntitySetHandle root_set
+  TYPE(C_PTR) :: vertsPtr, entsPtr
+  ! storage for vertex positions, element connectivity indices, global vertex ids
+  real*8 coords(0:3*NUMV-1)
+  integer iconn(0:4*NUME-1), gids(0:NUMV-1)
+  !
+  ! local variables
+  integer lgids(0:NUMV-1), lconn(0:4*NUME-1)
+  real*8 lcoords(0:3*NUMV-1)
+  integer lnumv, lvids(0:NUMV-1), gvids(0:NUMV-1)
+  integer lvpe, ltp ! lvpe = # vertices per entity, ltp = element type
+  integer ic, ie, iv, istart, iend, ierr, indv, lnume, rank, sz
+
+#ifdef USE_MPI
+  ! local variables for parallel runs
+  iMeshP_PartitionHandle imeshp
+  integer MPI_COMM_WORLD
+#endif
+
+  ! vertex positions, latlon coords, (lat, lon, lev), fortran ordering
+  ! (first index varying fastest)
+  data coords / &
+       0.0, -45.0,   0.0,  90.0, -45.0,   0.0, 180.0, -45.0,   0.0, 270.0, -45.0,   0.0, &
+       0.0,  45.0,   0.0,  90.0,  45.0,   0.0, 180.0,  45.0,   0.0, 270.0,  45.0,   0.0 /
+
+  ! quad index numbering, each quad ccw, sides then bottom then top
+  data iconn / & 
+       0, 1, 5, 4,  & 
+       1, 2, 6, 5,  & 
+       2, 3, 7, 6,  & 
+       3, 0, 4, 7,  & 
+       0, 3, 2, 1,  & 
+       4, 5, 6, 7 /
+
+  data lvpe /4/ ! quads in this example
+  data ltp / iMesh_QUADRILATERAL / ! from iBase_f.h
+
+  ! initialize global vertex ids
+  do iv = 0, NUMV-1
+     lgids(iv) = iv+1
+  end do
+
+#ifdef USE_MPI
+  ! init the parallel partition
+  call MPI_INIT(ierr)
+  call MPI_COMM_SIZE(MPI_COMM_WORLD, sz, ierr)
+  call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
+  ! compute starting/ending element numbers
+  lnume = NUME / sz
+  istart = rank * lnume
+  iend = istart + lnume - 1
+  if (rank .eq. sz-1) then
+     iend = NUME-1
+     lnume = iend - istart + 1
+  endif
+#else
+  ! set the starting/ending element numbers
+  istart = 0
+  iend = NUME-1
+  lnume = NUME
+#endif
+
+  ! for my elements, figure out which vertices I use and accumulate local indices and coords
+  ! lvids stores the local 0-based index for each vertex; -1 means vertex i isn't used locally
+  ! also build up connectivity indices for local elements, in lconn
+  do iv = 0, NUMV-1
+     lvids(iv) = -1
+  end do
+  lnumv = -1
+  do ie = istart, iend
+     do iv = 0, lvpe-1
+        indv = iconn(lvpe*ie + iv)
+        if (lvids(indv) .eq. -1) then
+           lnumv = lnumv + 1 ! increment local # verts
+           do ic = 0, 2 ! cache local coords
+              lcoords(3*lnumv+ic) = coords(3*indv+ic)
+           end do
+           lvids(indv) = lnumv
+           gvids(lnumv) = 1+indv
+        end if
+        lconn(lvpe*(ie-istart)+iv) = lvids(indv)
+     end do  ! do iv
+  end do  ! do ie
+  
+  lnumv = lnumv + 1
+
+  ! now create the mesh; this also initializes parallel sharing and ghost exchange
+  imesh = 0
+  imeshp = 0
+  call create_mesh(imesh, imeshp, MPI_COMM_WORLD, lnumv, lnume, gvids, lvpe, ltp, lcoords, lconn, &
+       vertsPtr, entsPtr, ierr)
+  call c_f_pointer(vertsPtr, verts, [lnumv])
+  call c_f_pointer(entsPtr, ents, [lnume])
+
+  ! get/report number of vertices, elements
+  call iMesh_getRootSet(%VAL(imesh), root_set, ierr)
+  iv = 0
+  ie = 0
+#ifdef USE_MPI
+  call iMeshP_getNumOfTypeAll(%VAL(imesh), %VAL(imeshp), %VAL(root_set), %VAL(iBase_VERTEX), iv, ierr)
+  call iMeshP_getNumOfTypeAll(%VAL(imesh), %VAL(imeshp), %VAL(root_set), %VAL(iBase_FACE), ie, ierr)
+  if (rank .eq. 0) then
+     write(0,*) "Number of vertices = ", iv
+     write(0,*) "Number of entities = ", ie
+  endif
+#else
+  call iMesh_getNumOfTypeAll(%VAL(imesh), %VAL(root_set), %VAL(iBase_VERTEX), iv, ierr)
+  call iMesh_getNumOfTypeAll(%VAL(imesh), %VAL(root_set), %VAL(iBase_FACE), ie, ierr)
+  write(0,*) "Number of vertices = ", iv
+  write(0,*) "Number of entities = ", ie
+#endif
+
+  ! from here, can use verts and ents as (1-based) arrays of entity handles for input to other iMesh functions
+
+  call MPI_FINALIZE(ierr)
+  stop
+end program PushParMeshIntoMoab
+
+subroutine create_mesh( &
+  !     interfaces
+     imesh, imeshp, &
+  !     input
+     comm, numv, nume, vgids, nvpe, tp, posn, iconn, &
+  !     output
+     vertsPtr, entsPtr, ierr)
+  !
+  ! create a mesh with numv vertices and nume elements, with elements of type tp
+  ! vertices have positions in posn (3 coordinates each, interleaved xyzxyz...), indexed from 0
+  ! elements have nvpe vertices per entity, with connectivity indices stored in iconn, referencing
+  ! vertices using 0-based indices; vertex and entity handles are output in arrays passed in
+  !
+  ! if imesh/imeshp are 0, imesh/imeshp are initialized in this subroutine
+  !
+
+  use ISO_C_BINDING
+  implicit none
+
+#ifdef USE_MPI
+#  include "iMeshP_f.h"
+#  include "mpif.h"
+#else
+#  include "iMesh_f.h"
+#endif
+
+  ! subroutine arguments
+  iMesh_Instance imesh
+  TYPE(C_PTR) :: vertsPtr, entsPtr
+  integer numv, nume, nvpe, vgids(0:*), iconn(0:*), ierr, tp
+  real*8 posn(0:*)
+#ifdef USE_MPI
+  iMeshP_PartitionHandle imeshp
+  integer comm
+#endif
+
+  ! local variables
+  integer comm_sz, comm_rank, numa, numo, iv, ie
+  TYPE(C_PTR) :: statsPtr
+  integer, allocatable, target :: stats(:)
+  iBase_TagHandle tagh
+  integer i
+  iBase_EntityHandle, pointer :: verts(:), ents(:)
+  iBase_EntityHandle, allocatable :: conn(:)
+  iBase_EntitySetHandle root_set
+#ifdef USE_MPI
+  IBASE_HANDLE_T mpi_comm_c
+  TYPE(C_PTR) :: partsPtr
+  iMeshP_PartHandle, pointer :: parts(:)
+  iMeshP_PartHandle part
+  integer partsa, partso
+#endif
+
+  ! create the Mesh instance
+  if (imesh .eq. 0) then
+     call iMesh_newMesh("MOAB", imesh, ierr)
+  end if
+
+#ifdef USE_MPI
+  if (imeshp .eq. 0) then
+     call iMeshP_getCommunicator(%VAL(imesh), MPI_COMM_WORLD, mpi_comm_c, ierr)
+     call iMeshP_createPartitionAll(%VAL(imesh), %VAL(mpi_comm_c), imeshp, ierr)
+     call iMeshP_createPart(%VAL(imesh), %VAL(imeshp), part, ierr)
+  else 
+     partsa = 0
+     call iMeshP_getLocalParts(%VAL(imesh), %VAL(imeshp), partsPtr, partsa, partso, ierr)
+     call c_f_pointer(partsPtr, parts, [partso])
+     part = parts(1)
+  end if
+  call MPI_COMM_RANK(comm, comm_rank, ierr)
+  call MPI_COMM_SIZE(comm, comm_sz, ierr)
+#endif
+
+  ! create the vertices, all in one call
+  numa = 0
+  call iMesh_createVtxArr(%VAL(imesh), %VAL(numv), %VAL(iBase_INTERLEAVED), posn, %VAL(3*numv), &
+       vertsPtr, numa, numo, ierr)
+
+  ! fill in the connectivity array, based on indexing from iconn
+  allocate (conn(0:nvpe*nume-1))
+  call c_f_pointer(vertsPtr, verts, [numv])
+  do i = 0, nvpe*nume-1
+     conn(i) = verts(1+iconn(i))
+  end do
+  ! create the elements
+  numa = 0
+  allocate(stats(0:nume-1))
+  statsPtr = C_LOC(stats(0))
+  call iMesh_createEntArr(%VAL(imesh), %VAL(tp), conn, %VAL(nvpe*nume), &
+       entsPtr, numa, numo, statsPtr, numa, numo, ierr)
+  deallocate(stats)
+  deallocate(conn)
+
+#ifdef USE_MPI
+  ! take care of parallel stuff
+
+  ! add entities to part, using iMesh
+  call c_f_pointer(entsPtr, ents, [numo])
+  call iMesh_addEntArrToSet(%VAL(imesh), ents, %VAL(numo), %VAL(part), ierr)
+  ! set global ids on vertices, needed for sharing between procs
+  call iMesh_getTagHandle(%VAL(imesh), "GLOBAL_ID", tagh, ierr, %VAL(9))
+  if (iBase_SUCCESS .ne. ierr) then
+     ! didn't get handle, need to create the tag
+     call iMesh_createTag(%VAL(imesh), "GLOBAL_ID", %VAL(iBase_INTEGER), tagh, ierr, %VAL(9))
+  end if
+  call iMesh_setIntArrData(%VAL(imesh), verts, %VAL(numv), %VAL(tagh), vgids, %VAL(numv), ierr)
+
+  ! now resolve shared verts and exchange ghost cells
+  call iMeshP_syncMeshAll(%VAL(imesh), %VAL(imeshp), ierr)
+  call iMesh_getRootSet(%VAL(imesh), root_set, ierr)
+  call iMeshP_getNumOfTypeAll(%VAL(imesh), %VAL(imeshp), %VAL(root_set), %VAL(iBase_VERTEX), iv, ierr)
+  call iMeshP_getNumOfTypeAll(%VAL(imesh), %VAL(imeshp), %VAL(root_set), %VAL(iBase_FACE), ie, ierr)
+  if (comm_rank .eq. 0) then
+     write(0,*) "After syncMeshAll:"
+     write(0,*) "   Number of vertices = ", iv
+     write(0,*) "   Number of entities = ", ie
+  endif
+
+  call iMeshP_createGhostEntsAll(%VAL(imesh), %VAL(imeshp), %VAL(2), %VAL(1), %VAL(1), %VAL(0), ierr)
+  if (comm_rank .eq. 0) then
+     write(0,*) "After createGhostEntsAll:"
+     write(0,*) "   Number of vertices = ", iv
+     write(0,*) "   Number of entities = ", ie
+  endif
+#endif
+
+  return
+end subroutine create_mesh

diff --git a/examples/makefile b/examples/makefile
index ff5876c..cd6339e 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -9,7 +9,7 @@ MESH_DIR="../MeshFiles/unittest"
 
 EXAMPLES = HelloMOAB GetEntities SetsNTags StructuredMeshSimple DirectAccessWithHoles DirectAccessNoHoles 
 PAREXAMPLES = HelloParMOAB ReduceExchangeTags LloydRelaxation
-F90EXAMPLES = DirectAccessNoHolesF90
+F90EXAMPLES = DirectAccessNoHolesF90 PushParMeshIntoMoabF90
 EXOIIEXAMPLES = TestExodusII
 
 default: ${EXAMPLES}
@@ -50,12 +50,15 @@ TestExodusII: TestExodusII.o
 point_in_elem_search: point_in_elem_search.o
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
+PushParMeshIntoMoabF90: PushParMeshIntoMoabF90.o
+	${MOAB_CXX} -o $@ $< ${IMESH_LIBS} -lgfortran -L/usr/lib/openmpi/lib -lmpi_f90 -lmpi_f77 -lmpi -lopen-rte -lopen-pal -ldl 
+
 clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 
 .cpp.o :
-	${MOAB_CXX} ${MOAB_CXXFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
+	${MOAB_CXX} ${CXXFLAGS} ${MOAB_CXXFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 
 .F90.o :
-	${IMESH_FC} ${IMESH_FCFLAGS} ${IMESH_INCLUDES} ${IMESH_FCDEFS} -DMESH_DIR=\"${MESH_DIR}\" -c $<
+	${IMESH_FC} ${FCFLAGS} ${IMESH_FCFLAGS} ${IMESH_INCLUDES} ${IMESH_FCDEFS} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 

diff --git a/itaps/imesh/iMeshP_MOAB.cpp b/itaps/imesh/iMeshP_MOAB.cpp
index 51254ca..b7e8333 100644
--- a/itaps/imesh/iMeshP_MOAB.cpp
+++ b/itaps/imesh/iMeshP_MOAB.cpp
@@ -1606,11 +1606,8 @@ void iMeshP_syncMeshAll( iMesh_Instance instance,
                          const iMeshP_PartitionHandle partition_handle,
                          int *err )
 {
-  FIXME; // for now we only sync vertex coordinates
-         // need to update ParallelComm::update_shared_mesh to fix this
-
   ParallelComm* pcomm = PCOMM;
-  ErrorCode rval = pcomm->update_shared_mesh();
+  ErrorCode rval = pcomm->resolve_shared_ents(itaps_cast<EntityHandle>(partition_handle), -1, -1);
   CHKERR(rval,"update failed");
   RETURN (iBase_SUCCESS);
 }

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index ebf149c..bc41ab2 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -295,7 +295,7 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
   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();
+  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)
@@ -748,16 +748,20 @@ ErrorCode NCHelper::create_dummy_variables()
     dummyVarNames.insert(dimNames[i]);
     dbgOut.tprintf(2, "Dummy variable created for dimension %s\n", dimNames[i].c_str());
 
-    // Create a sparse tag to store the dimension length
+    // Create a corresponding sparse tag
     Tag tagh;
-    ErrorCode rval = mbImpl->tag_get_handle(dimNames[i].c_str(), 1, MB_TYPE_INTEGER, tagh,
-                                            MB_TAG_SPARSE | MB_TAG_CREAT | MB_TAG_EXCL);
+    ErrorCode rval = mbImpl->tag_get_handle(dimNames[i].c_str(), 0, MB_TYPE_INTEGER, tagh, MB_TAG_CREAT |
+                                            MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL);
     // If the tag already exists, skip
     if (MB_ALREADY_ALLOCATED == rval)
       continue;
-    ERRORR(rval, "Failed to create dimension tag.");
+    ERRORR(rval, "Failed to create tag for a dummy dimension variable.");
 
-    rval = mbImpl->tag_set_data(tagh, &_fileSet, 1, &dimLens[i]);
+    // Tag value is the dimension length
+    const void* ptr = &dimLens[i];
+    // Tag size is 1
+    int size = 1;
+    rval = mbImpl->tag_set_by_ptr(tagh, &_fileSet, 1, &ptr, &size);
     ERRORR(rval, "Failed to set data for dimension tag.");
 
     dbgOut.tprintf(2, "Sparse tag created for dimension %s\n", dimNames[i].c_str());

diff --git a/src/parallel/ParallelComm.cpp b/src/parallel/ParallelComm.cpp
index 8efc777..bcc555a 100644
--- a/src/parallel/ParallelComm.cpp
+++ b/src/parallel/ParallelComm.cpp
@@ -2093,7 +2093,19 @@ ErrorCode ParallelComm::recv_entities(std::set<unsigned int>& recv_procs,
 
         if (new_h && store_remote_handles) {
           unsigned char new_pstat = 0x0;
-          if (is_iface) new_pstat = PSTATUS_INTERFACE;
+          if (is_iface) {
+            new_pstat = PSTATUS_INTERFACE;
+              // here, lowest rank proc should be first
+            int idx = std::min_element(&ps[0], &ps[0]+num_ps) - &ps[0];
+            if (idx) {
+              std::swap(ps[0], ps[idx]);
+              std::swap(hs[0], hs[idx]);
+            }
+              // set ownership based on lowest rank; can't be in update_remote_data, because
+              // there we don't know whether it resulted from ghosting or not
+            if ((num_ps > 1 && ps[0] != (int) rank()))
+              new_pstat |= PSTATUS_NOT_OWNED;
+          }
           else if (created_here) {
             if (created_iface) new_pstat = PSTATUS_NOT_OWNED;
             else new_pstat = PSTATUS_GHOST | PSTATUS_NOT_OWNED;
@@ -2542,17 +2554,14 @@ ErrorCode ParallelComm::recv_entities(std::set<unsigned int>& recv_procs,
     }
 
       // add myself, if it isn't there already
-    idx = 0;
-    if (new_ps[0] != (int)rank()) {
-      idx = std::find(&new_ps[0], &new_ps[0] + new_numps, rank()) - &new_ps[0];
-      if (idx == new_numps) {
-        new_ps[new_numps] = rank();
-        new_hs[new_numps] = new_h;
-        new_numps++;
-      }
-      else if (!new_hs[idx] && new_numps > 2)
-        new_hs[idx] = new_h;
+    idx = std::find(&new_ps[0], &new_ps[0] + new_numps, rank()) - &new_ps[0];
+    if (idx == new_numps) {
+      new_ps[new_numps] = rank();
+      new_hs[new_numps] = new_h;
+      new_numps++;
     }
+    else if (!new_hs[idx] && new_numps > 2)
+      new_hs[idx] = new_h;
 
       // proc list is complete; update for shared, multishared
     if (new_numps > 1) {
@@ -2560,18 +2569,6 @@ ErrorCode ParallelComm::recv_entities(std::set<unsigned int>& recv_procs,
       new_pstat |= PSTATUS_SHARED;
     }
 
-      // if multishared, not ghost or interface, and not not_owned, I'm owned, and should be the first proc
-    assert(new_ps[idx] == (int)rank());
-    if ((new_numps > 2 && !(new_pstat&(PSTATUS_INTERFACE|PSTATUS_GHOST|PSTATUS_NOT_OWNED))) ||
-        (new_pstat&PSTATUS_INTERFACE && !(new_pstat&PSTATUS_NOT_OWNED))
-        ) {
-      idx = std::min_element(&new_ps[0], &new_ps[0] + new_numps) - &new_ps[0];
-      std::swap(new_ps[0], new_ps[idx]);
-      std::swap(new_hs[0], new_hs[idx]);
-      if (new_ps[0] != (int)rank())
-        new_pstat |= PSTATUS_NOT_OWNED;
-    }
-
 /*    
     plist("new_ps", new_ps, new_numps);
     plist("new_hs", new_hs, new_numps);
@@ -3723,15 +3720,21 @@ ErrorCode ParallelComm::resolve_shared_ents(EntityHandle this_set,
         return result;
       }
     }
-  
-    // get the entities in the partition sets
-    for (Range::iterator rit = partitionSets.begin(); rit != partitionSets.end(); rit++) {
-      Range tmp_ents;
-      result = mbImpl->get_entities_by_handle(*rit, tmp_ents, true);
+
+    if (0 == this_set) {
+        // get the entities in the partition sets
+      for (Range::iterator rit = partitionSets.begin(); rit != partitionSets.end(); rit++) {
+        Range tmp_ents;
+        result = mbImpl->get_entities_by_handle(*rit, tmp_ents, true);
+        if (MB_SUCCESS != result) return result;
+        proc_ents.merge(tmp_ents);
+      }
+    }
+    else {
+      result = mbImpl->get_entities_by_handle(this_set, proc_ents, true);
       if (MB_SUCCESS != result) return result;
-      proc_ents.merge(tmp_ents);
     }
-
+      
     // resolve dim is maximal dim of entities in proc_ents
     if (-1 == resolve_dim) {
       if (proc_ents.empty()) 
@@ -7566,146 +7569,6 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
     }
   */
 
-  ErrorCode ParallelComm::update_shared_mesh()
-  {
-    //  ErrorCode result;
-    //  int success;
-
-    // ,,,
-    /*
-
-    // get all procs interfacing to this proc
-    std::set<unsigned int> iface_procs;
-    result = get_interface_procs(iface_procs);
-    RRA("Failed to get iface sets, procs");
-
-    // post ghost irecv's for all interface procs
-    // index greqs the same as buffer/sharing procs indices
-    std::vector<MPI_Request> recv_reqs(2*MAX_SHARING_PROCS, MPI_REQUEST_NULL);
-    std::vector<MPI_Status> gstatus(MAX_SHARING_PROCS);
-    std::set<unsigned int>::iterator sit;
-    for (sit = iface_procs.begin(); sit != iface_procs.end(); sit++) {
-    int ind = get_buffers(*sit);
-    success = MPI_Irecv(&ghostRBuffs[ind][0], ghostRBuffs[ind].size(), 
-    MPI_UNSIGNED_CHAR, *sit,
-    MB_MESG_ANY, procConfig.proc_comm(), 
-    &recv_reqs[ind]);
-    if (success != MPI_SUCCESS) {
-    result = MB_FAILURE;
-    RRA("Failed to post irecv in ghost exchange.");
-    }
-    }
-  
-    // pack and send vertex coordinates from this proc to others
-    // make sendReqs vector to simplify initialization
-    std::fill(sendReqs, sendReqs+2*MAX_SHARING_PROCS, MPI_REQUEST_NULL);
-    Range recd_ents[MAX_SHARING_PROCS];
-  
-    for (sit = iface_procs.begin(); sit != iface_procs.end(); sit++) {
-    int ind = get_buffers(*sit);
-    
-    Range vertices;
-    for (Range::iterator rit = interfaceSets.begin(); rit != interfaceSets.end();
-    rit++) {
-    if (!is_iface_proc(*rit, *sit)) 
-    continue;
-      
-    result = mbImpl->get_entities_by_type( *rit, MBVERTEX, vertices );
-    RRA("Bad interface set.");
-    }
-    std::map<unsigned int,Range>::iterator ghosted = ghostedEnts.find(*sit);
-    if (ghosted != ghostedEnts.end()) {
-    Range::iterator e = ghosted->second.upper_bound(MBVERTEX);
-    vertices.merge( ghosted->second.begin(), e );
-    }
-
-    // pack-send; this also posts receives if store_remote_handles is true
-    Range sent;
-    result = pack_send_entities(*sit, vertices, false, false, 
-    false, true,
-    ownerSBuffs[ind], ownerRBuffs[MAX_SHARING_PROCS+ind], 
-    sendReqs[ind], recv_reqs[MAX_SHARING_PROCS+ind], 
-    sent);
-    RRA("Failed to pack-send in mesh update exchange.");
-    }
-  
-    // receive/unpack entities
-    // number of incoming messages depends on whether we're getting back
-    // remote handles
-    int num_incoming = iface_procs.size();
-  
-    while (num_incoming) {
-    int ind;
-    MPI_Status status;
-    success = MPI_Waitany(2*MAX_SHARING_PROCS, &recv_reqs[0], &ind, &status);
-    if (MPI_SUCCESS != success) {
-    result = MB_FAILURE;
-    RRA("Failed in waitany in ghost exchange.");
-    }
-    
-    // ok, received something; decrement incoming counter
-    num_incoming--;
-    
-    std::vector<EntityHandle> remote_handles_v, sent_ents_tmp;
-    Range remote_handles_r;
-    int new_size;
-    
-    // branch on message type
-    switch (status.MPI_TAG) {
-    case MB_MESG_SIZE:
-    // incoming message just has size; resize buffer and re-call recv,
-    // then re-increment incoming count
-    assert(ind < MAX_SHARING_PROCS);
-    new_size = *((int*)&ghostRBuffs[ind][0]);
-    assert(0 > new_size);
-    result = recv_size_buff(buffProcs[ind], ghostRBuffs[ind], recv_reqs[ind],
-    MB_MESG_ENTS);
-    RRA("Failed to resize recv buffer.");
-    num_incoming++;
-    break;
-    case MB_MESG_ENTS:
-    // incoming ghost entities; process
-    result = recv_unpack_entities(buffProcs[ind], true,
-    false, 
-    ghostRBuffs[ind], ghostSBuffs[ind], 
-    sendReqs[ind], recd_ents[ind]);
-    RRA("Failed to recv-unpack message.");
-    break;
-    }
-    }
-  
-    // ok, now wait if requested
-    MPI_Status status[2*MAX_SHARING_PROCS];
-    success = MPI_Waitall(2*MAX_SHARING_PROCS, &sendReqs[0], status);
-    if (MPI_SUCCESS != success) {
-    result = MB_FAILURE;
-    RRA("Failure in waitall in ghost exchange.");
-    }
-  
-    return MB_SUCCESS;
-    }
-    ErrorCode ParallelComm::update_iface_sets(Range &sent_ents,
-    std::vector<EntityHandle> &remote_handles, 
-    int from_proc) 
-    {
-    std::vector<EntityHandle>::iterator remote_it = remote_handles.begin();
-    Range::iterator sent_it = sent_ents.begin();
-    Range ents_to_remove;
-    for (; sent_it != sent_ents.end(); sent_it++, remote_it++) {
-    if (!*remote_it) ents_to_remove.insert(*sent_it);
-    }
-  
-    for (Range::iterator set_it = interfaceSets.begin(); set_it != interfaceSets.end(); set_it++) {
-    if (!is_iface_proc(*set_it, from_proc)) continue;
-    ErrorCode result = mbImpl->remove_entities(*set_it, ents_to_remove);
-    RRA("Couldn't remove entities from iface set in update_iface_sets.");
-    }
-
-    */
-  
-    return MB_SUCCESS;
-  }
-
   //! return sharedp tag
   Tag ParallelComm::sharedp_tag()
   {
@@ -8414,7 +8277,8 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
         continue;
       }
  
-      if (!shents.empty()) check_my_shared_handles(shents);
+      if (!shents.empty()) 
+        result = check_my_shared_handles(shents);
       done = true;
     }
   
@@ -8586,6 +8450,7 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
 
     Range bad_ents, local_shared;
     std::vector<SharedEntityData>::iterator vit;
+    unsigned char tmp_pstat;
     for (unsigned int i = 0; i < shents.size(); i++) {
       int other_proc = buffProcs[i];
       result = get_shared_entities(other_proc, local_shared);
@@ -8596,6 +8461,11 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
         result = get_remote_handles(true, &localh, &dumh, 1, other_proc, dum_vec);
         if (MB_SUCCESS != result || dumh != remoteh) 
           bad_ents.insert(localh);
+        result = get_pstatus(localh, tmp_pstat);
+        if (MB_SUCCESS != result ||
+            (!tmp_pstat&PSTATUS_NOT_OWNED && vit->owner != rank()) ||
+            (tmp_pstat&PSTATUS_NOT_OWNED && vit->owner == rank()))
+          bad_ents.insert(localh);
       }
 
       if (!local_shared.empty()) 
@@ -8603,10 +8473,9 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsigned int>& shared_procs,
     }
   
     if (!bad_ents.empty()) {
-      if (prefix) {
+      if (prefix)
         std::cout << prefix << std::endl;
-        list_entities(bad_ents);
-      }
+      list_entities(bad_ents);
       return MB_FAILURE;
     }
 

diff --git a/src/parallel/moab/ParallelComm.hpp b/src/parallel/moab/ParallelComm.hpp
index e4217ce..3424c51 100644
--- a/src/parallel/moab/ParallelComm.hpp
+++ b/src/parallel/moab/ParallelComm.hpp
@@ -697,10 +697,6 @@ namespace moab {
                                  int& num_part_ids_out,
                                  EntityHandle remote_handles[MAX_SHARING_PROCS] = 0);
   
-    // Propogate mesh modification amongst shared entities
-    // from the onwing processor to any procs with copies.
-    ErrorCode update_shared_mesh();
-
     /** Filter the entities by pstatus tag.  
      * op is one of PSTATUS_ AND, OR, NOT; an entity is output if:
      * AND: all bits set in pstatus_val are also set on entity

diff --git a/test/parallel/parallel_unit_tests.cpp b/test/parallel/parallel_unit_tests.cpp
index 85cc3b8..d2d4c5b 100644
--- a/test/parallel/parallel_unit_tests.cpp
+++ b/test/parallel/parallel_unit_tests.cpp
@@ -1445,12 +1445,11 @@ template <typename T> ErrorCode check_shared_ents(ParallelComm &pcomm, Tag tagh,
   for (rit = shared_ents.begin(); rit != shared_ents.end(); rit++, i++) {
     rval = pcomm.get_sharing_data(*rit, &shprocs[0], &shhandles[0], pstatus, np); CHKERR(rval);
     if (1 == np && shprocs[0] != (int) pcomm.proc_config().proc_rank()) np++;
+    bool with_root = std::find(&shprocs[0], &shprocs[np], 0)-&shprocs[0] != np || !pcomm.rank();
     if      (mpi_op == MPI_SUM) {if (dum_vals[i] != fact*np) return MB_FAILURE;}
     else if (mpi_op == MPI_PROD) {if (dum_vals[i] != pow(fact, np)) return MB_FAILURE;}
-    else if (mpi_op == MPI_MAX) {if (pcomm.rank() && std::find(&shprocs[0],&shprocs[np], 0) != &shprocs[np] &&
-                                     dum_vals[i] != fact) return MB_FAILURE;}
-    else if (mpi_op == MPI_MIN) {if (pcomm.rank() && std::find(&shprocs[0],&shprocs[np], 0) != &shprocs[np] &&
-                                     dum_vals[i] != fact) return MB_FAILURE;}
+    else if (mpi_op == MPI_MAX) {if (with_root && dum_vals[i] != fact) return MB_FAILURE;}
+    else if (mpi_op == MPI_MIN) {if (with_root && dum_vals[i] != fact) return MB_FAILURE;}
     else return MB_FAILURE;
   }
   

diff --git a/test/parallel/structured3.cpp b/test/parallel/structured3.cpp
index 17ad177..daf065b 100644
--- a/test/parallel/structured3.cpp
+++ b/test/parallel/structured3.cpp
@@ -14,6 +14,12 @@ using namespace moab;
  
   // Number of cells in each direction:
 int NC;
+
+/* This mesh creates a box that is NCxNCxNC in global dimension, partitioned among processors
+ * automatically using ScdInterface's SQIJK algorithm.  It checks to make sure there are enough
+ * procs to support this partition method.  After mesh creation, shared vertex resolution is done,
+ * then ghost exchange is done.
+ */
 const int ITERS = 50;
  
 void create_parallel_mesh();
@@ -60,7 +66,7 @@ void create_parallel_mesh()
   times[0] = MPI_Wtime();
   rval = scdi->construct_box(HomCoord(), HomCoord(), NULL, 0, // no vertex positions
                              new_box, NULL, // not locally periodic
-                             &par_data, true, false); // assign global ids & resolve shared verts
+                             &par_data, true, false); // assign global ids, don't resolve shared verts
   CHECK_ERR(rval);
 
     // get global id tag


https://bitbucket.org/fathomteam/moab/commits/59346457c95d/
Changeset:   59346457c95d
Branch:      None
User:        danwu
Date:        2013-12-04 21:47:26
Summary:     Merged fathomteam/moab into master
Affected #:  42 files

diff --git a/.gitignore b/.gitignore
index 4e0534c..e824a6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,17 +25,22 @@ config/test-driver
 configure
 .cproject
 *.cub
+cubit??.jou
 .deps
 doc/config.tex
 doc/dev.dox
 doc/user/*
 doc/user.dox
 examples/examples.make
+examples/DeformMeshRemap
+examples/DirectAccessNoHoles
+examples/DirectAccessWithHoles
 examples/FileRead
 examples/GeomSetHierarchy
 examples/GetEntities
 examples/*.h5m
-examples/HelloMoabPar
+examples/HelloMOAB
+examples/HelloParMOAB
 examples/itaps/FindConnectF
 examples/itaps/ListSetsNTagsCXX
 examples/itaps/ListSetsNTagsF90
@@ -47,8 +52,12 @@ examples/PushParMeshIntoMoabF90
 examples/ReduceExchangeTags
 examples/SetsNTags
 examples/SkinMesh
+examples/StructuredMeshSimple
 examples/SurfArea
 examples/TestExodusII
+history??.jou
+hpctoolkit-*
+*.hpcstruct
 include
 include/*
 itaps/iBase_f.h

diff --git a/Makefile.am b/Makefile.am
index 1c91622..b8c3c9e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,7 +48,7 @@ install-data-hook:
 	echo -n "SET(MOAB_LIBRARIES \"" >> $(DESTDIR)$(cfgdir)/MOABConfig.cmake
 # next line: get the post-substitution set of link commands, then filter out leading
 # and trailing spaces, then terminate with close-quote and close-paren
-	echo -n "@EXPORT_LDFLAGS@ -L$(MOAB_LIBDIR) -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@" | \
+	echo -n "@EXPORT_LDFLAGS@ -L$(libdir) -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @CGNS_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@" | \
 	   sed -e 's/^ *//;s/ *$$/\")\n/' >> $(DESTDIR)$(cfgdir)/MOABConfig.cmake
 
 # Generate a file to be installed in $libdir containing the configuration

diff --git a/MeshFiles/unittest/io/2d_naca0012.cgns b/MeshFiles/unittest/io/2d_naca0012.cgns
new file mode 100644
index 0000000..4ce0452
Binary files /dev/null and b/MeshFiles/unittest/io/2d_naca0012.cgns differ

diff --git a/MeshFiles/unittest/io/Makefile.am b/MeshFiles/unittest/io/Makefile.am
index fb8a265..dbce393 100644
--- a/MeshFiles/unittest/io/Makefile.am
+++ b/MeshFiles/unittest/io/Makefile.am
@@ -7,6 +7,7 @@ EXTRA_DIST = HommeMapping.nc \
 	     cubtest12.cub \
 	     cubtest.jou \
 	     dum.sat \
+	     dum.stp \
 	     gmsh2.msh \
 	     hex_2x2x2_ss.exo \
              ho_test.g \
@@ -19,6 +20,7 @@ EXTRA_DIST = HommeMapping.nc \
              test.unv \
 	     sample.stl \
              three.smf \
-             mpasx1.642.t.2.nc
+             mpasx1.642.t.2.nc \
+             2d_naca0012.cgns
 
 

diff --git a/config/cgns.m4 b/config/cgns.m4
new file mode 100644
index 0000000..16b19e3
--- /dev/null
+++ b/config/cgns.m4
@@ -0,0 +1,92 @@
+#######################################################################################
+# Check for CGNS library
+# Sets HAVE_CGNS to 'yes' or 'no'
+# If HAVE_CGNS == yes, then exports:
+#   CGNS_CPPFLAGS
+#   CGNS_LDFLAGS
+#   CGNS_LIBS
+#######################################################################################
+AC_DEFUN([FATHOM_CHECK_CGNS],[
+
+AC_MSG_CHECKING([if CGNS support is enabled])
+AC_ARG_WITH(cgns, 
+[AC_HELP_STRING([--with-cgns<:@=DIR@:>@], [Specify CGNS library to use for CGNS file format])
+AC_HELP_STRING([--without-cgns], [Disable support for CGNS file format])],
+[CGNS_ARG=$withval
+DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS --with-cgns=\"${withval}\""
+]
+, [CGNS_ARG=])
+if test "xno" != "x$CGNS_ARG"; then
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+ # if CGNS support is not disabled
+HAVE_CGNS=no
+if test "xno" != "x$CGNS_ARG"; then
+  HAVE_CGNS=yes
+  
+    # if a path is specified, update LIBS and INCLUDES accordingly
+  if test "xyes" != "x$CGNS_ARG" && test "x" != "x$CGNS_ARG"; then
+    if test -d "${CGNS_ARG}/lib"; then
+      CGNS_LDFLAGS="-L${CGNS_ARG}/lib"
+    elif test -d "${CGNS_ARG}"; then
+      CGNS_LDFLAGS="-L${CGNS_ARG}"
+    else
+      AC_MSG_ERROR("$CGNS_ARG is not a directory.")
+    fi
+    if test -d "${CGNS_ARG}/include"; then
+      CGNS_CPPFLAGS="-I${CGNS_ARG}/include"
+    elif test -d "${CGNS_ARG}/inc"; then
+      CGNS_CPPFLAGS="-I${CGNS_ARG}/inc"
+    else
+      CGNS_CPPFLAGS="-I${CGNS_ARG}"
+    fi
+  fi
+  
+  old_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CGNS_CPPFLAGS $CPPFLAGS"
+  old_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$CGNS_LDFLAGS $HDF5_LDFLAGS $LDFLAGS"
+  
+   # Check for C library
+  AC_LANG_PUSH([C])
+
+  AC_CHECK_HEADER([cgnslib.h], [],
+                  [AC_MSG_WARN([[CGNS header not found.]]); HAVE_CGNS=no] )
+
+      # Check if cgns is usable by itself
+  AC_CHECK_LIB( [cgns], [cg_open], [CGNS_LIBS="-lcgns"], [
+      # Check if cgns is usable with HDF5
+    unset ac_cv_lib_cgns
+    unset ac_cv_lib_cgns_cg_open
+      # If we haven't already looked for HDF5 libraries, again now incase
+      # they're in the CGNS lib directory.
+    FATHOM_DETECT_HDF5_LIBS
+    LDFLAGS="$LDFLAGS $HDF5_LDFLAGS"
+    AC_CHECK_LIB( [cgns], [cg_open], [CGNS_LIBS="-lcgns -lhdf5_hl"], [
+      # Try one more time with HDF5 and libcurl
+      unset ac_cv_lib_cgns
+      unset ac_cv_lib_cgns_cg_open
+      AC_CHECK_LIB( [cgns], [cg_open], [CGNS_LIBS="-lcgns -lhdf5_hl -lcurl"], 
+        [HAVE_CGNS=no], [-lhdf5_hl $HDF5_LIBS -lcurl] )],
+      [-lhdf5_hl $HDF5_LIBS] )],
+    )
+  
+  CPPFLAGS="$old_CPPFLAGS"
+  LDFLAGS="$old_LDFLAGS"
+  AC_LANG_POP([C])
+
+  if test "x$HAVE_CGNS" = "xno"; then
+    if test "x$CGNS_ARG" != "x"; then 
+      AC_MSG_ERROR("CGNS not found or not working")
+    else
+      AC_MSG_WARN("CGNS support disabled")
+    fi
+    CGNS_CPPFLAGS=
+    CGNS_LDFLAGS=
+  fi
+fi
+
+]) # FATHOM_HAVE_CGNS

diff --git a/configure.ac b/configure.ac
index bdc225b..ea22a5e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -446,6 +446,22 @@ AM_CPPFLAGS="$PNETCDF_CPPFLAGS $AM_CPPFLAGS"
 EXPORT_LDFLAGS="$PNETCDF_LDFLAGS $EXPORT_LDFLAGS"
 AC_SUBST(PNETCDF_LIBS)
 
+################################################################################
+#                             CGNS OPTIONS
+################################################################################
+
+old_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $HDF5_LDFLAGS"
+FATHOM_CHECK_CGNS
+LDFLAGS="$old_LDFLAGS"
+if test "xno" != "x$HAVE_CGNS"; then
+  AM_CPPFLAGS="$AM_CPPFLAGS -DCGNS_FILE"
+fi
+AM_CONDITIONAL(CGNS_FILE, [test "xno" != "x$HAVE_CGNS"])
+AM_CPPFLAGS="$CGNS_CPPFLAGS $AM_CPPFLAGS"
+EXPORT_LDFLAGS="$CGNS_LDFLAGS $EXPORT_LDFLAGS"
+AC_SUBST(CGNS_LIBS)
+
 
 #################################################################################
 #                             Documentation

diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
index 8f4a6be..4f86821 100644
--- a/doc/UG/moabUG.h
+++ b/doc/UG/moabUG.h
@@ -731,6 +731,11 @@ The options used to specify loading method, the data used to identify parts, and
 <td><gd.bd.nl[.ad]></td><td>Exchange ghost elements at shared inter-processor interfaces.  Ghost elements of dimension gd will be exchanged.  Ghost elements are chosen going through bd-dimensional interface entities.  Number of layers of ghost elements is specified in nl.  If ad is present, lower-dimensional entities bounding exchanged ghost entities will also be exchanged; allowed values for ad are 1 (exchange bounding edges), 2 (faces), or 3 (edges and faces).</td></tr>
+<td>PARALLEL_COMM</td>
+<td><id></td>
+<td>Use the ParallelComm with index <id>.  Index for a ParallelComm object can be checked with ParallelComm::get_id(), and a ParallelComm with a given index can be retrieved using ParallelComm::get_pcomm(id).</td>
+</tr>
+<tr><tr><td>CPUTIME</td><td>(none)</td>

diff --git a/examples/PushParMeshIntoMoabF90.F90 b/examples/PushParMeshIntoMoabF90.F90
index 131d19c..2d5a0f4 100644
--- a/examples/PushParMeshIntoMoabF90.F90
+++ b/examples/PushParMeshIntoMoabF90.F90
@@ -16,6 +16,8 @@ program PushParMeshIntoMoab
   use ISO_C_BINDING
   implicit none
 
+#include "mpif.h"
+
 #ifdef USE_MPI
 #  include "iMeshP_f.h"
 #else
@@ -49,7 +51,7 @@ program PushParMeshIntoMoab
 #ifdef USE_MPI
   ! local variables for parallel runs
   iMeshP_PartitionHandle imeshp
-  integer MPI_COMM_WORLD
+!    integer MPI_COMM_WORLD
 #endif
 
   ! vertex positions, latlon coords, (lat, lon, lev), fortran ordering

diff --git a/examples/makefile b/examples/makefile
index cd6339e..5ae5af0 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -57,8 +57,8 @@ clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 
 .cpp.o :
-	${MOAB_CXX} ${CXXFLAGS} ${MOAB_CXXFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
+	${MOAB_CXX} ${CXXFLAGS} ${MOAB_CXXFLAGS} ${MOAB_CPPFLAGS} ${MOAB_INCLUDES} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 
-.F90.o :
-	${IMESH_FC} ${FCFLAGS} ${IMESH_FCFLAGS} ${IMESH_INCLUDES} ${IMESH_FCDEFS} -DMESH_DIR=\"${MESH_DIR}\" -c $<
+ .F90.o :
+	${IMESH_FC} ${FCFLAGS} ${IMESH_FCFLAGS} ${MOAB_CPPFLAGS} ${IMESH_INCLUDES} ${IMESH_FCDEFS} -DMESH_DIR=\"${MESH_DIR}\" -c $<
 

diff --git a/itaps/imesh/iMesh-Defs.inc.in b/itaps/imesh/iMesh-Defs.inc.in
index b0b7f70..314b536 100644
--- a/itaps/imesh/iMesh-Defs.inc.in
+++ b/itaps/imesh/iMesh-Defs.inc.in
@@ -7,7 +7,7 @@ IMESH_FCFLAGS = @FCFLAGS@
 
 IMESH_FCDEFS = @DEFS@
 
-IMESH_CPPFLAGS = -I$(IMESH_INCLUDEDIR) $(IMESH_INCLUDEDIR2)
+IMESH_CPPFLAGS = @CPPFLAGS@ @AM_CPPFLAGS@ -I$(IMESH_INCLUDEDIR) $(IMESH_INCLUDEDIR2)
 
 # This definition is deprecated; use IMESH_CPPFLAGS instead
 IMESH_INCLUDES = $(IMESH_CPPFLAGS)

diff --git a/moab.make.in b/moab.make.in
index 45f80de..ebb3caa 100644
--- a/moab.make.in
+++ b/moab.make.in
@@ -10,13 +10,14 @@ MOAB_INCLUDES = -I at abs_srcdir@/src \
 
 MOAB_INCLUDES += @ZOLTAN_INC_FLAGS@
 
+MOAB_CPPFLAGS = @CPPFLAGS@ @AM_CPPFLAGS@
 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@ @ZOLTAN_LIBS@ 
+MOAB_LIBS_LINK = ${MOAB_LDFLAGS} -L${MOAB_LIBDIR} -lMOAB @LIBS@ @PNETCDF_LIBS@ @NETCDF_LIBS@ @CGNS_LIBS@ @HDF5_LIBS@ @CCMIO_LIBS@ @CGM_LIBS@ @ZOLTAN_LIBS@ 
 
 MOAB_CXX = @CXX@
 MOAB_CC  = @CC@

diff --git a/src/Core.cpp b/src/Core.cpp
index a6e6cfd..0bd882f 100644
--- a/src/Core.cpp
+++ b/src/Core.cpp
@@ -69,16 +69,20 @@
 #  ifdef HDF5_PARALLEL
 #    include "WriteHDF5Parallel.hpp"
      typedef moab::WriteHDF5Parallel DefaultWriter;
+#    define DefaultWriterName "WriteHDF5Parallel"
 #  else
 #    include "WriteHDF5.hpp"
      typedef moab::WriteHDF5 DefaultWriter;
+#    define DefaultWriterName "WriteHDF5"
 #  endif
 #elif defined(NETCDF_FILE)
 #  include "WriteNCDF.hpp"
    typedef moab::WriteNCDF DefaultWriter;
+#  define DefaultWriterName "WriteNCDF"
 #else
 #  include "WriteVtk.hpp"
    typedef moab::WriteVtk DefaultWriter;
+#  define DefaultWriterName "WriteVtk"
 #endif
 #include "MBTagConventions.hpp"
 #include "ExoIIUtil.hpp"
@@ -727,7 +731,10 @@ ErrorCode Core::write_file( const char* file_name,
       rval = writer->write_file(file_name, overwrite, opts, list_ptr, list.size(), qa_records,
                                 tag_list, num_tags );
       if (rval != MB_SUCCESS)
+      {
         mError->set_last_error( "Writer for file type \"%s\" was unsuccessful", file_type);
+        printf("Writer with name %s for file %s using extension %s was unsuccessful\n",i->name().c_str(), file_name, ext.c_str());
+      }
       delete writer;
     }
   }
@@ -737,6 +744,7 @@ ErrorCode Core::write_file( const char* file_name,
 
   else if (MB_SUCCESS != rval) {
     DefaultWriter writer(this);
+    printf("Using default writer %s for file %s \n", DefaultWriterName, file_name);
     rval = writer.write_file(file_name, overwrite, opts, list_ptr, list.size(), qa_records,
                              tag_list, num_tags );
   }

diff --git a/src/Makefile.am b/src/Makefile.am
index 64b8a0f..0eb07c5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -157,7 +157,6 @@ nobase_libMOAB_la_include_HEADERS = \
   moab/GeomTopoTool.hpp \
   moab/HigherOrderFactory.hpp \
   moab/HomXform.hpp \
-  moab/EigenDecomp.hpp \
   moab/EntityType.hpp \
   moab/EntityHandle.hpp \
   moab/FBEngine.hpp \

diff --git a/src/OrientedBox.cpp b/src/OrientedBox.cpp
index caab7d1..0932952 100644
--- a/src/OrientedBox.cpp
+++ b/src/OrientedBox.cpp
@@ -274,7 +274,7 @@ ErrorCode OrientedBox::compute_from_vertices( OrientedBox& result,
 
     // Get axes (Eigenvectors) from covariance matrix
   double lambda[3];
-  EigenDecomp( a, lambda, result.axis );
+  moab::Matrix::EigenDecomp( a, lambda, result.axis );
   
     // Calculate center and extents of box given orientation defined by axes
   return box_from_axes( result, instance, vertices );
@@ -369,7 +369,7 @@ ErrorCode OrientedBox::compute_from_covariance_data(
 
     // get axes (Eigenvectors) from covariance matrix
   double lamda[3];
-  EigenDecomp( data.matrix, lamda, result.axis );
+  moab::Matrix::EigenDecomp( data.matrix, lamda, result.axis );
 
     // We now have only the axes.  Calculate proper center
     // and extents for enclosed points.

diff --git a/src/ReaderWriterSet.cpp b/src/ReaderWriterSet.cpp
index 8185b34..5015a7f 100644
--- a/src/ReaderWriterSet.cpp
+++ b/src/ReaderWriterSet.cpp
@@ -1,16 +1,16 @@
 /**
  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
  * storing and accessing finite element mesh data.
- * 
+ *
  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
  * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
  * retains certain rights in this software.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
- * 
+ *
  */
 
 #include "moab/Core.hpp"
@@ -54,11 +54,16 @@
 #endif
 
 // 2nd include of ReadNC in case we have pnetcdf and not netcdf
-#ifdef PNETCDF_FILE 
+#ifdef PNETCDF_FILE
 #  include "ReadNC.hpp"
 #  include "ReadGCRM.hpp"
 #endif
 
+#ifdef CGNS_FILE
+#  include "ReadCGNS.hpp"
+#  include "WriteCGNS.hpp"
+#endif
+
 #ifdef CCMIO_FILE
 #  include "ReadCCMIO.hpp"
 #  include "WriteCCMIO.hpp"
@@ -83,15 +88,15 @@
 namespace moab {
 
 ReaderWriterSet::ReaderWriterSet( Core* mdb, Error* handler )
-  : mbCore( mdb ), mbError( handler ) 
+  : mbCore( mdb ), mbError( handler )
 {
 #ifdef HDF5_FILE
   const char* hdf5_sufxs[] = { "h5m", "mhdf", NULL };
 #ifdef HDF5_PARALLEL
-  register_factory(  ReadHDF5::factory, WriteHDF5Parallel::factory, 
+  register_factory(  ReadHDF5::factory, WriteHDF5Parallel::factory,
                      "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
 #else
-  register_factory(  ReadHDF5::factory, WriteHDF5::factory, 
+  register_factory(  ReadHDF5::factory, WriteHDF5::factory,
                      "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
 #endif
 #endif
@@ -103,21 +108,26 @@ ReaderWriterSet::ReaderWriterSet( Core* mdb, Error* handler )
   register_factory( ReadNC::factory, NULL, "Climate NC", "nc", "NC" );
 #endif
 
+#ifdef CGNS_FILE
+  const char* cgns_sufxs[] = { "cgns", NULL };
+  register_factory( ReadCGNS::factory, WriteCGNS::factory, "CGNS", cgns_sufxs, "CGNS" );
+#endif
+
   register_factory( ReadIDEAS::factory, NULL, "IDEAS format", "unv", "UNV" );
-  
+
   register_factory( ReadMCNP5::factory, NULL, "MCNP5 format", "meshtal", "MESHTAL" );
-  
+
   const char* nastran_sufxs[] = { "nas", "bdf", NULL };
   register_factory( ReadNASTRAN::factory, NULL, "NASTRAN format", nastran_sufxs, "NAS" );
 
   register_factory( ReadABAQUS::factory, NULL, "ABAQUS INP mesh format", "abq", "Abaqus mesh" );
-  
+
   register_factory( ReadVtk::factory, WriteVtk::factory, "Kitware VTK", "vtk", "VTK" );
-  
+
   register_factory( ReadSms::factory, NULL, "RPI SMS", "sms", "SMS" );
-  
+
   register_factory( Tqdcfr::factory, NULL, "Cubit", "cub", "CUBIT" );
-  
+
   register_factory( ReadSmf::factory, WriteSmf::factory , "QSlim format", "smf", "SMF");
 
 #ifdef CGM
@@ -131,27 +141,27 @@ ReaderWriterSet::ReaderWriterSet( Core* mdb, Error* handler )
   register_factory( ReadCGM::factory, NULL, "IGES B-Rep exchange", iges_sufxs, "IGES");
 #endif
 
-#ifdef NETCDF_FILE  
+#ifdef NETCDF_FILE
   register_factory( NULL, WriteSLAC::factory, "SLAC", "slac", "SLAC" );
 #endif
 
-#ifdef CCMIO_FILE  
+#ifdef CCMIO_FILE
   const char* ccmio_sufxs[] = { "ccm", "ccmg", NULL };
   register_factory( ReadCCMIO::factory, WriteCCMIO::factory, "CCMIO files", ccmio_sufxs, "CCMIO");
 #endif
 
-#ifdef DAMSEL_FILE  
+#ifdef DAMSEL_FILE
   const char* damsel_sufxs[] = { "h5", NULL };
   register_factory( ReadDamsel::factory, WriteDamsel::factory, "Damsel files", damsel_sufxs, "DAMSEL");
 #endif
 
   register_factory( NULL, WriteGMV::factory, "GMV", "gmv", "GMV" );
-  
+
   register_factory( NULL, WriteAns::factory, "Ansys", "ans", "ANSYS" );
-  
+
   const char* gmsh_sufxs[] = { "msh", "gmsh", NULL };
   register_factory( ReadGmsh::factory, WriteGmsh::factory, "Gmsh mesh file", gmsh_sufxs, "GMSH" );
-  
+
   register_factory( ReadSTL::factory, WriteSTL::factory, "Stereo Lithography File (STL)", "stl", "STL" );
 
   const char* tetgen_sufxs[] = { "node", "ele", "face", "edge", NULL };
@@ -178,7 +188,7 @@ ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
 {
   if (!reader && !writer)
     return MB_FAILURE;
-    
+
     // check for duplicate names
   iterator h = handler_by_name( name );
   if (h != end()) {
@@ -186,7 +196,7 @@ ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
                              name );
     return MB_FAILURE;
   }
-  
+
     // count extensions and check for duplicates
   const char* const* iter;
   for (iter = extensions; *iter; ++iter)
@@ -206,7 +216,7 @@ ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
   }
   handlerList.push_back( Handler(reader, writer, name, description, extensions, iter - extensions) );
   return MB_SUCCESS;
-}    
+}
 
 ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
                                                  writer_factory_t writer,
@@ -218,8 +228,8 @@ ErrorCode ReaderWriterSet::register_factory( reader_factory_t reader,
   return register_factory( reader, writer, description, extensions, name );
 }
 
-  
-ReaderIface* ReaderWriterSet::get_file_extension_reader( 
+
+ReaderIface* ReaderWriterSet::get_file_extension_reader(
                                   const std::string& filename ) const
 {
   std::string ext = extension_from_filename( filename );
@@ -227,7 +237,7 @@ ReaderIface* ReaderWriterSet::get_file_extension_reader(
   return handler == end() ? NULL : handler->make_reader(mbCore);
 }
 
-WriterIface* ReaderWriterSet::get_file_extension_writer( 
+WriterIface* ReaderWriterSet::get_file_extension_writer(
                                   const std::string& filename ) const
 {
   std::string ext = extension_from_filename( filename );
@@ -235,7 +245,7 @@ WriterIface* ReaderWriterSet::get_file_extension_writer(
   return handler == end() ? NULL : handler->make_writer(mbCore);
 }
 
-std::string ReaderWriterSet::extension_from_filename( 
+std::string ReaderWriterSet::extension_from_filename(
                                  const std::string& filename )
 {
   std::string::size_type idx = filename.find_last_of( "." );
@@ -245,11 +255,11 @@ std::string ReaderWriterSet::extension_from_filename(
     return filename.substr( idx + 1 );
 }
 
-ReaderWriterSet::Handler::Handler( reader_factory_t read_f, 
+ReaderWriterSet::Handler::Handler( reader_factory_t read_f,
                                      writer_factory_t write_f,
                                      const char* nm,
-                                     const char* desc, 
-                                     const char* const* ext, 
+                                     const char* desc,
+                                     const char* const* ext,
                                      int num_ext )
  : mReader(read_f), mWriter(write_f), mName(nm), mDescription(desc), mExtensions(num_ext)
 {
@@ -261,45 +271,45 @@ ReaderWriterSet::Handler::Handler( reader_factory_t read_f,
 #define strcasecmp(A,B) _stricmp( A, B )
 #endif
 
-ReaderWriterSet::iterator 
+ReaderWriterSet::iterator
 ReaderWriterSet::handler_from_extension( const std::string& ext,
                                            bool with_reader,
                                            bool with_writer ) const
 {
   iterator iter;
   std::vector<std::string>::const_iterator siter;
-  
+
     // try case-sensitive compare
   for (iter = begin(); iter != end(); ++iter)
   {
     if ((with_reader && !iter->have_reader()) ||
         (with_writer && !iter->have_writer()))
       continue;
-      
+
     for (siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter)
       if (*siter == ext)
         return iter;
   }
-  
+
     // try case-insensitive compare
   for (iter = begin(); iter != end(); ++iter)
   {
     if ((with_reader && !iter->have_reader()) ||
         (with_writer && !iter->have_writer()))
       continue;
- 
+
     for (siter = iter->mExtensions.begin(); siter != iter->mExtensions.end(); ++siter)
       if (0 == strcasecmp( siter->c_str(), ext.c_str() ))
         return iter;
   }
-  
+
   return end();
 }
 
-bool ReaderWriterSet::Handler::reads_extension(const char *ext) const 
+bool ReaderWriterSet::Handler::reads_extension(const char *ext) const
 {
   if (!have_reader()) return false;
-  
+
   std::vector<std::string>::const_iterator siter;
   for (siter = mExtensions.begin(); siter != mExtensions.end(); ++siter)
     if (!(*siter).compare(ext)) return true;
@@ -308,10 +318,10 @@ bool ReaderWriterSet::Handler::reads_extension(const char *ext) const
   return false;
 }
 
-bool ReaderWriterSet::Handler::writes_extension(const char *ext) const 
+bool ReaderWriterSet::Handler::writes_extension(const char *ext) const
 {
   if (!have_writer()) return false;
-  
+
   std::vector<std::string>::const_iterator siter;
   for (siter = mExtensions.begin(); siter != mExtensions.end(); ++siter)
     if (!(*siter).compare(ext)) return true;
@@ -335,7 +345,7 @@ bool ReaderWriterSet::Handler::operator==( const char* nm ) const
       return false;
   return *nm == '\0';
 }
-  
+
 } // namespace moab
 
 

diff --git a/src/io/ExoIIUtil.cpp b/src/io/ExoIIUtil.cpp
index ef9156b..61d9b9e 100644
--- a/src/io/ExoIIUtil.cpp
+++ b/src/io/ExoIIUtil.cpp
@@ -54,6 +54,7 @@ const EntityType ExoIIUtil::ExoIIElementMBEntity[] =
   MBQUAD, // SHELL9,
   MBTET, // TETRA,
   MBTET, // TETRA4,
+  MBTET, // TET4
   MBTET, // TETRA8,
   MBTET, // TETRA10,
   MBTET, // TETRA14,
@@ -102,7 +103,8 @@ const char* ExoIIUtil::ElementTypeNames[] =
   "SHELL8", 
   "SHELL9",
   "TETRA", 
-  "TETRA4", 
+  "TETRA4",
+  "TET4",
   "TETRA8", 
   "TETRA10", 
   "TETRA14",
@@ -151,6 +153,7 @@ const int ExoIIUtil::VerticesPerElement[] =
   9,  // SHELL
   4, 
   4,  
+  4,  // TET4
   8, 
   10, 
   14,  // TETRA
@@ -199,6 +202,7 @@ const int ExoIIUtil::HasMidNodes[][4] =
   {0, 1, 1, 0}, // SHELL9 - mid nodes on edges and faces
   {0, 0, 0, 0}, // TETRA - no mid nodes
   {0, 0, 0, 0}, // TETRA4 - no mid nodes
+  {0, 0, 0, 0}, // TET4 - no mid nodes
   {0, 0, 1, 0}, // TETRA8 - mid nodes on faces
   {0, 1, 0, 0}, // TETRA10 - mid nodes on edges
   {0, 1, 1, 0}, // TETRA14 - mid nodes on edges and faces
@@ -250,6 +254,7 @@ const int ExoIIUtil::ElementGeometricDimension[] =
   3, 
   3, 
   3, // TETRA
+  3,
   3, 
   3, 
   3, 

diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index 60caa48..09fe3d3 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -7,7 +7,7 @@ endif
 
 # Things to build
 noinst_LTLIBRARIES = libmoabio.la 
-libmoabio_la_LIBADD = $(NETCDF_LIBS) $(PNETCDF_LIBS) $(HDF5_LIBS) 
+libmoabio_la_LIBADD = $(NETCDF_LIBS) $(PNETCDF_LIBS) $(CGNS_LIBS) $(HDF5_LIBS) 
 
 AM_CPPFLAGS += -DIS_BUILDING_MB \
                -I..  -I$(srcdir)/.. -I$(srcdir)/../parallel
@@ -43,6 +43,13 @@ if ENABLE_mbzoltan
   AM_CPPFLAGS += -I$(srcdir)/../../tools/mbzoltan $(ZOLTAN_INC_FLAGS) 
 endif
 
+if CGNS_FILE
+  MOAB_CGNS_SRCS = ReadCGNS.cpp  ReadCGNS.hpp \
+                   WriteCGNS.cpp  WriteCGNS.hpp
+else
+  MOAB_CGNS_SRCS =
+endif
+
 if HDF5_FILE
   libmoabio_la_LIBADD += mhdf/libmhdf.la
   MOAB_HDF5_SRCS = HDF5Common.cpp \
@@ -139,6 +146,7 @@ libmoabio_la_SOURCES = \
   WriteVtk.cpp \
   WriteVtk.hpp \
   $(MOAB_NETCDF_SRCS) \
+  $(MOAB_CGNS_SRCS) \
   $(MOAB_HDF5_SRCS) \
   $(MOAB_CCMIO_SRCS) \
   $(MOAB_DAMSEL_SRCS) \

diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index bc41ab2..c915382 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -139,7 +139,7 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
 
   // __<dim_name>_LOC_MINMAX (for time)
   for (unsigned int i = 0; i != dimNamesSz; i++) {
-    if (dimNames[i] == "time") {
+    if (dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t") {
       std::stringstream ss_tag_name;
       ss_tag_name << "__" << dimNames[i] << "_LOC_MINMAX";
       tag_name = ss_tag_name.str();
@@ -158,7 +158,7 @@ ErrorCode NCHelper::create_conventional_tags(const std::vector<int>& tstep_nums)
 
   // __<dim_name>_LOC_VALS (for time)
   for (unsigned int i = 0; i != dimNamesSz; i++) {
-    if (dimNames[i] == "time") {
+    if (dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t") {
       std::vector<int> val;
       if (!tstep_nums.empty())
         val = tstep_nums;
@@ -310,13 +310,13 @@ ErrorCode NCHelper::read_variable_setup(std::vector<std::string>& var_names, std
   std::map<std::string, ReadNC::VarData>& varInfo = _readNC->varInfo;
   std::map<std::string, ReadNC::VarData>::iterator mit;
 
-  // If empty read them all
+  // If empty read them all (except ignored variables)
   if (var_names.empty()) {
     for (mit = varInfo.begin(); mit != varInfo.end(); ++mit) {
       ReadNC::VarData vd = (*mit).second;
 
-      // No need to read ignored variables. Upon creation of dummy variables,
-      // tag values have already been set
+      // If read all variables at once, skip ignored ones
+      // Upon creation of dummy variables, tag values have already been set
       if (ignoredVarNames.find(vd.varName) != ignoredVarNames.end() ||
           dummyVarNames.find(vd.varName) != dummyVarNames.end())
          continue;
@@ -328,15 +328,14 @@ ErrorCode NCHelper::read_variable_setup(std::vector<std::string>& var_names, std
     }
   }
   else {
+    // Read specified variables (might include ignored ones)
     for (unsigned int i = 0; i < var_names.size(); i++) {
       mit = varInfo.find(var_names[i]);
       if (mit != varInfo.end()) {
         ReadNC::VarData vd = (*mit).second;
 
-        // No need to read ignored variables. Upon creation of dummy variables,
-        // tag values have already been set
-        if (ignoredVarNames.find(vd.varName) != ignoredVarNames.end() ||
-            dummyVarNames.find(vd.varName) != dummyVarNames.end())
+        // Upon creation of dummy variables, tag values have already been set
+        if (dummyVarNames.find(vd.varName) != dummyVarNames.end())
            continue;
 
         if (vd.entLoc == ReadNC::ENTLOCSET)
@@ -360,23 +359,24 @@ ErrorCode NCHelper::read_variable_setup(std::vector<std::string>& var_names, std
     for (unsigned int i = 0; i < vdatas.size(); i++) {
       vdatas[i].varTags.resize(tstep_nums.size(), 0);
       vdatas[i].varDatas.resize(tstep_nums.size());
-      vdatas[i].readStarts.resize(tstep_nums.size());
-      vdatas[i].readCounts.resize(tstep_nums.size());
+      vdatas[i].has_tsteps = true;
     }
 
     for (unsigned int i = 0; i < vsetdatas.size(); i++) {
       if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim) != vsetdatas[i].varDims.end())
-          && (vsetdatas[i].varDims.size() != 1)) {
+          && (vsetdatas[i].varDims.size() > 1)) {
+        // Set variables with timesteps: time is the first dimension, followed
+        // by other dimensions, e.g. xtime(Time, StrLen)
         vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
         vsetdatas[i].varDatas.resize(tstep_nums.size());
-        vsetdatas[i].readStarts.resize(tstep_nums.size());
-        vsetdatas[i].readCounts.resize(tstep_nums.size());
+        vsetdatas[i].has_tsteps = true;
       }
       else {
+        // Set variables without timesteps: no time dimension, or time is the only
+        // dimension, e.g. lev(lev), xtime(Time)
         vsetdatas[i].varTags.resize(1, 0);
         vsetdatas[i].varDatas.resize(1);
-        vsetdatas[i].readStarts.resize(1);
-        vsetdatas[i].readCounts.resize(1);
+        vsetdatas[i].has_tsteps = false;
       }
     }
   }
@@ -395,35 +395,41 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
   // Finally, read into that space
   int success;
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // Note, for set variables without timesteps, loop one time and then break
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
       void* data = vdatas[i].varDatas[t];
 
+      // Set variables with timesteps, e.g. xtime(Time, StrLen)
+      if (vdatas[i].has_tsteps) {
+        // Set readStart for each timestep along time dimension
+        vdatas[i].readStarts[0] = tstep_nums[t];
+      }
+
       switch (vdatas[i].varDataType) {
         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);
+          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
+                                        &vdatas[i].readCounts[0], (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);
+          success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
+                                        &vdatas[i].readCounts[0], (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);
+        case NC_FLOAT:
+          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
+                                        &vdatas[i].readCounts[0], (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);
+          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
+                                        &vdatas[i].readCounts[0], (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);
+          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
+                                        &vdatas[i].readCounts[0], (short*) data);
           ERRORS(success, "Failed to read short data.");
           break;
         default:
@@ -438,10 +444,30 @@ ErrorCode NCHelper::read_variable_to_set(std::vector<ReadNC::VarData>& vdatas, s
       ERRORR(rval, "Failed to convert variable.");
 
       dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t]);
-      rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+      rval = mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], &_fileSet, 1, &data, &vdatas[i].sz);
       ERRORR(rval, "Failed to set data for variable.");
 
-      if (vdatas[i].varDims.size() <= 1 || !vdatas[i].has_t)
+      // Memory pointed by pointer data can be deleted, as tag_set_by_ptr() has already copied the tag values
+      switch (vdatas[i].varDataType) {
+        case NC_BYTE:
+        case NC_CHAR:
+          delete[] (char*) data;
+          break;
+        case NC_DOUBLE:
+        case NC_FLOAT:
+          delete[] (double*) data;
+          break;
+        case NC_INT:
+        case NC_SHORT:
+          delete[] (int*) data;
+          break;
+        default:
+          break;
+      }
+      vdatas[i].varDatas[t] = NULL;
+
+      // Loop continues only for set variables with timesteps, e.g. xtime(Time, StrLen)
+      if (!vdatas[i].has_tsteps)
         break;
     }
   }
@@ -583,14 +609,11 @@ ErrorCode NCHelper::get_tag_to_set(ReadNC::VarData& var_data, int tstep_num, Tag
   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
+  if (var_data.has_tsteps)
     tag_name << var_data.varName << tstep_num;
+  else
+    tag_name << var_data.varName;
+
   ErrorCode rval = MB_SUCCESS;
   tagh = 0;
   switch (var_data.varDataType) {
@@ -623,12 +646,8 @@ ErrorCode NCHelper::get_tag_to_nonset(ReadNC::VarData& var_data, int tstep_num,
   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;
+  tag_name << var_data.varName << tstep_num;
+
   ErrorCode rval = MB_SUCCESS;
   tagh = 0;
   switch (var_data.varDataType) {
@@ -750,11 +769,8 @@ ErrorCode NCHelper::create_dummy_variables()
 
     // Create a corresponding sparse tag
     Tag tagh;
-    ErrorCode rval = mbImpl->tag_get_handle(dimNames[i].c_str(), 0, MB_TYPE_INTEGER, tagh, MB_TAG_CREAT |
-                                            MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_EXCL);
-    // If the tag already exists, skip
-    if (MB_ALREADY_ALLOCATED == rval)
-      continue;
+    ErrorCode rval = mbImpl->tag_get_handle(dimNames[i].c_str(), 0, MB_TYPE_INTEGER, tagh,
+                                            MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
     ERRORR(rval, "Failed to create tag for a dummy dimension variable.");
 
     // Tag value is the dimension length
@@ -778,75 +794,71 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarData>&
   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 || dimLens[tDim] <= (int) t)
-        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+    // Set up readStarts and readCounts
+    if (vdatas[i].has_tsteps) {
+      // First: time
+      vdatas[i].readStarts.push_back(0); // This value is timestep dependent, will be set later
+      vdatas[i].readCounts.push_back(1);
 
-      // 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());
-        }
+      // Next: other dimensions
+      for (unsigned int idx = 1; idx != vdatas[i].varDims.size(); idx++){
+        vdatas[i].readStarts.push_back(0);
+        vdatas[i].readCounts.push_back(dimLens[vdatas[i].varDims[idx]]);
       }
-
-      // Set up other dimensions and counts
+    }
+    else {
       if (vdatas[i].varDims.empty()) {
         // Scalar variable
-        vdatas[i].readStarts[t].push_back(0);
-        vdatas[i].readCounts[t].push_back(1);
+        vdatas[i].readStarts.push_back(0);
+        vdatas[i].readCounts.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(dimLens[vdatas[i].varDims[idx]]);
-          }
+          vdatas[i].readStarts.push_back(0);
+          vdatas[i].readCounts.push_back(dimLens[vdatas[i].varDims[idx]]);
         }
       }
+    }
+
+    // Get variable size
+    vdatas[i].sz = 1;
+    for (std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++)
+      vdatas[i].sz *= vdatas[i].readCounts[idx];
+
+    // Note, for set variables without timesteps, loop one time and then break
+    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::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;
+      if (tstep_nums[t] >= dimLens[tDim]) {
+        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for a timestep number.");
+      }
+
+      // 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 for a set variable.");
+      }
 
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         case NC_CHAR:
-          vdatas[i].varDatas[t] = new char[sz];
+          vdatas[i].varDatas[t] = new char[vdatas[i].sz];
           break;
         case NC_DOUBLE:
         case NC_FLOAT:
-          vdatas[i].varDatas[t] = new double[sz];
+          vdatas[i].varDatas[t] = new double[vdatas[i].sz];
           break;
         case NC_INT:
         case NC_SHORT:
-          vdatas[i].varDatas[t] = new int[sz];
+          vdatas[i].varDatas[t] = new int[vdatas[i].sz];
           break;
         default:
-          std::cerr << "Unrecognized data type for tag " << std::endl;
+          std::cerr << "Unrecognized data type for set variable tag values" << std::endl;
           rval = MB_FAILURE;
       }
 
-      if (vdatas[i].varDims.size() <= 1 || !vdatas[i].has_t)
+      // Loop continues only for set variables with timesteps, e.g. xtime(Time, StrLen)
+      if (!vdatas[i].has_tsteps)
         break;
     }
   }
@@ -1059,70 +1071,73 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
 #endif
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // Support non-set variables with 4 dimensions like (time, lev, lat, lon)
+    assert(4 == vdatas[i].varDims.size());
+
+    // For a non-set variable, time should be the first dimension
+    assert(tDim == vdatas[i].varDims[0]);
+
+    // Set up readStarts and readCounts
+    vdatas[i].readStarts.resize(4);
+    vdatas[i].readCounts.resize(4);
+
+    // First: time
+    vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
+    vdatas[i].readCounts[0] = 1;
+
+    // Next: lev
+    vdatas[i].readStarts[1] = 0;
+    vdatas[i].readCounts[1] = vdatas[i].numLev;
+
+    // Finally: lat (or slat) and lon (or slon)
+    switch (vdatas[i].entLoc) {
+      case ReadNC::ENTLOCVERT:
+        // Vertices
+        vdatas[i].readStarts[2] = lDims[1];
+        vdatas[i].readCounts[2] = lDims[4] - lDims[1] + 1;
+        vdatas[i].readStarts[3] = lDims[0];
+        vdatas[i].readCounts[3] = lDims[3] - lDims[0] + 1;
+        range = &verts;
+        break;
+      case ReadNC::ENTLOCNSEDGE:
+        ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+        break;
+      case ReadNC::ENTLOCEWEDGE:
+        ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+        break;
+      case ReadNC::ENTLOCFACE:
+        // Faces
+        vdatas[i].readStarts[2] = lCDims[1];
+        vdatas[i].readCounts[2] = lCDims[4] - lCDims[1] + 1;
+        vdatas[i].readStarts[3] = lCDims[0];
+        vdatas[i].readCounts[3] = lCDims[3] - lCDims[0] + 1;
+#ifdef USE_MPI
+        range = &faces_owned;
+#else
+        range = &faces;
+#endif
+        break;
+      case ReadNC::ENTLOCSET:
+        // Set
+        break;
+      default:
+        ERRORR(MB_FAILURE, "Unrecognized entity location type.");
+        break;
+    }
+
     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]);
 
+      if (tstep_nums[t] >= dimLens[tDim]) {
+        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for a timestep number.");
+      }
+
       // Get the tag to read into
       if (!vdatas[i].varTags[t]) {
         rval = get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);
         ERRORR(rval, "Trouble getting tag.");
       }
 
-      // Assume point-based values for now?
-      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) {
-        ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given for time-independent variable.");
-      }
-
-      // Set up the dimensions and counts
-      // First: time
-      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
-      vdatas[i].readCounts[t].push_back(1);
-
-      // Next: numLev, even if it is 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
-          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]);
-          vdatas[i].readCounts[t].push_back(lDims[3] - lDims[0] + 1);
-          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
-          range = &verts;
-          break;
-        case ReadNC::ENTLOCNSEDGE:
-          ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
-          break;
-        case ReadNC::ENTLOCEWEDGE:
-          ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
-          break;
-        case ReadNC::ENTLOCFACE:
-          // Faces
-          vdatas[i].readStarts[t].push_back(lCDims[1]);
-          vdatas[i].readCounts[t].push_back(lCDims[4] - lCDims[1] + 1);
-          vdatas[i].readStarts[t].push_back(lCDims[0]);
-          vdatas[i].readCounts[t].push_back(lCDims[3] - lCDims[0] + 1);
-          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
-#ifdef USE_MPI
-          range = &faces_owned;
-#else
-          range = &faces;
-#endif
-          break;
-        case ReadNC::ENTLOCSET:
-          // Set
-          break;
-        default:
-          ERRORR(MB_FAILURE, "Unrecognized entity location type.");
-          break;
-      }
-
       // Get ptr to tag space
       void* data;
       int count;
@@ -1132,11 +1147,10 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(std::vector<ReadNC::
       vdatas[i].varDatas[t] = data;
     }
 
-    // Calculate variable size
-    std::size_t sz = 1;
-    for (std::size_t idx = 0; idx != vdatas[i].readCounts[0].size(); idx++)
-      sz *= vdatas[i].readCounts[0][idx];
-    vdatas[i].sz = sz;
+    // Get variable size
+    vdatas[i].sz = 1;
+    for (std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++)
+      vdatas[i].sz *= vdatas[i].readCounts[idx];
   }
 
   return rval;
@@ -1154,20 +1168,27 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(std::vector<ReadNC::VarData>&
   for (unsigned int i = 0; i < vdatas.size(); i++) {
     std::size_t sz = vdatas[i].sz;
 
+    // A typical supported variable: float T(time, lev, lat, lon)
+    // For tag values, need transpose (lev, lat, lon) to (lat, lon, lev)
+    size_t ni = vdatas[i].readCounts[3]; // lon or slon
+    size_t nj = vdatas[i].readCounts[2]; // lat or slat
+    size_t nk = vdatas[i].readCounts[1]; // lev
+
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
+      // Tag data for this timestep
       void* data = vdatas[i].varDatas[t];
-      size_t ni = vdatas[i].readCounts[t][2];
-      size_t nj = vdatas[i].readCounts[t][3];
-      size_t nk = vdatas[i].readCounts[t][1];
+
+      // Set readStart for each timestep along time dimension
+      vdatas[i].readStarts[0] = tstep_nums[t];
 
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         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]);
+          success = NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
+                                        &tmpchardata[0]);
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, lat, lon) to (lat, lon, lev)
             success = kji_to_jik(ni, nj, nk, data, &tmpchardata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpchardata.size(); idx++)
@@ -1178,10 +1199,10 @@ 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]);
+          success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
+                                          &tmpdoubledata[0]);
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, lat, lon) to (lat, lon, lev)
             success = kji_to_jik(ni, nj, nk, data, &tmpdoubledata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
@@ -1192,10 +1213,10 @@ 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]);
+          success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
+                                          &tmpfloatdata[0]);
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, lat, lon) to (lat, lon, lev)
             success = kji_to_jik(ni, nj, nk, data, &tmpfloatdata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpfloatdata.size(); idx++)
@@ -1206,10 +1227,10 @@ 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]);
+          success = NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
+                                        &tmpintdata[0]);
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, lat, lon) to (lat, lon, lev)
             success = kji_to_jik(ni, nj, nk, data, &tmpintdata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpintdata.size(); idx++)
@@ -1220,10 +1241,10 @@ 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]);
+          success = NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vdatas[i].readStarts[0], &vdatas[i].readCounts[0],
+                                          &tmpshortdata[0]);
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, lat, lon) to (lat, lon, lev)
             success = kji_to_jik(ni, nj, nk, data, &tmpshortdata[0]);
           else {
             for (std::size_t idx = 0; idx != tmpshortdata.size(); idx++)

diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 25c4441..efddb0c 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -525,49 +525,57 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC
       verts.psize() == 1);
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
-    vdatas[i].numLev = nLevels;
+    // Support non-set variables with 3 dimensions like (time, lev, ncol)
+    assert(3 == vdatas[i].varDims.size());
+
+    // For a non-set variable, time should be the first dimension
+    assert(tDim == vdatas[i].varDims[0]);
+
+    // Set up readStarts and readCounts
+    vdatas[i].readStarts.resize(3);
+    vdatas[i].readCounts.resize(3);
+
+    // First: time
+    vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
+    vdatas[i].readCounts[0] = 1;
+
+    // Next: lev
+    vdatas[i].readStarts[1] = 0;
+    vdatas[i].readCounts[1] = vdatas[i].numLev;
+
+    // Finally: ncol
+    switch (vdatas[i].entLoc) {
+      case ReadNC::ENTLOCVERT:
+        // Vertices
+        // Start from the first localGidVerts
+        // Actually, this will be reset later on in a loop
+        vdatas[i].readStarts[2] = localGidVerts[0] - 1;
+        vdatas[i].readCounts[2] = nLocalVertices;
+        range = &verts;
+        break;
+      default:
+        ERRORR(MB_FAILURE, "Unexpected entity location type for HOMME non-set variable.");
+        break;
+    }
+
+    // Get variable size
+    vdatas[i].sz = 1;
+    for (std::size_t idx = 0; idx != 3; idx++)
+      vdatas[i].sz *= vdatas[i].readCounts[idx];
 
     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]);
+
+      if (tstep_nums[t] >= dimLens[tDim]) {
+        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for a timestep number.");
+      }
+
       // Get the tag to read into
       if (!vdatas[i].varTags[t]) {
         rval = get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);
         ERRORR(rval, "Trouble getting tag.");
       }
 
-      // Assume point-based values for now?
-      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) {
-        ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given for time-independent variable.");
-      }
-
-      // Set up the dimensions and counts
-      // First: time
-      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
-      vdatas[i].readCounts[t].push_back(1);
-
-      // Next: numLev, even if it is 1
-      vdatas[i].readStarts[t].push_back(0);
-      vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-
-      // Finally: nVertices
-      switch (vdatas[i].entLoc) {
-        case ReadNC::ENTLOCVERT:
-          // Vertices
-          // 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(nLocalVertices);
-          assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size());
-          range = &verts;
-          break;
-        default:
-          ERRORR(MB_FAILURE, "Unexpected entity location type for HOMME non-set variable.");
-          break;
-      }
-
       // Get ptr to tag space
       void* data;
       int count;
@@ -576,12 +584,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC
       assert((unsigned)count == range->size());
       vdatas[i].varDatas[t] = data;
     }
-
-    // Calculate variable size
-    std::size_t sz = 1;
-    for (std::size_t idx = 0; idx != vdatas[i].readCounts[0].size(); idx++)
-      sz *= vdatas[i].readCounts[0][idx];
-    vdatas[i].sz = sz;
   }
 
   return rval;
@@ -601,16 +603,24 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
   for (unsigned int i = 0; i < vdatas.size(); i++) {
     std::size_t sz = vdatas[i].sz;
 
+    // A typical supported variable: float T(time, lev, ncol)
+    // For tag values, need transpose (lev, ncol) to (ncol, lev)
+    size_t ni = vdatas[i].readCounts[2]; // ncol
+    size_t nj = 1; // Here we should just set nj to 1
+    size_t nk = vdatas[i].readCounts[1]; // lev
+
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
       // We will synchronize all these reads with the other processors,
       // so the wait will be inside this double loop; is it too much?
       size_t nb_reads = localGidVerts.psize();
       std::vector<int> requests(nb_reads), statuss(nb_reads);
       size_t idxReq = 0;
+
+      // Tag data for this timestep
       void* data = vdatas[i].varDatas[t];
-      size_t ni = vdatas[i].readCounts[t][2];
-      size_t nj = 1; // For HOMME, nj holds # quads, so here should set to 1
-      size_t nk = vdatas[i].readCounts[t][1];
+
+      // Set readStart for each timestep along time dimension
+      vdatas[i].readStarts[0] = tstep_nums[t];
 
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
@@ -619,7 +629,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
           break;
         }
         case NC_DOUBLE: {
-          // Copy from float case
+          // Copied from float case
           std::vector<double> tmpdoubledata(sz);
 
           // In the case of ucd mesh, and on multiple proc,
@@ -627,10 +637,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
           // localGidVerts range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
-          // assume that the last dimension is for the ncol,
-          // node varying variable
-
           size_t indexInDoubleArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
@@ -638,13 +644,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[2] = (NCDF_SIZE) (endh - starth + 1);
 
             // Do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCREQG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                            &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpdoubledata[indexInDoubleArray]), &requests[idxReq++]);
             ERRORS(success, "Failed to read double data in loop");
             // We need to increment the index in double array for the
@@ -657,7 +663,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
           ERRORS(success, "Failed on wait_all.");
 
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, ncol) to (ncol, lev)
             success = kji_to_jik_stride(ni, nj, nk, data, &tmpdoubledata[0], localGidVerts);
           else {
             for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
@@ -674,9 +680,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
           // localGidVerts range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
-
-          // Assume that the last dimension is for the ncol, number of vertices
           size_t indexInFloatArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
@@ -684,13 +687,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[2] = (NCDF_SIZE) (endh - starth + 1);
 
             // Do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCREQG(_vara_float)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                            &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpfloatdata[indexInFloatArray]), &requests[idxReq++]);
             ERRORS(success, "Failed to read float data in loop");
             // We need to increment the index in float array for the
@@ -703,7 +706,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
           ERRORS(success, "Failed on wait_all.");
 
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, ncol) to (ncol, lev)
             success = kji_to_jik_stride(ni, nj, nk, data, &tmpfloatdata[0], localGidVerts);
           else {
             for (std::size_t idx = 0; idx != tmpfloatdata.size(); idx++)
@@ -737,6 +740,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(std::vector<ReadNC::V
         rval = tmp_rval;
     }
   }
+
   // Debug output, if requested
   if (1 == dbgOut.get_verbosity()) {
     dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str());
@@ -760,11 +764,18 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
   for (unsigned int i = 0; i < vdatas.size(); i++) {
     std::size_t sz = vdatas[i].sz;
 
+    // A typical supported variable: float T(time, lev, ncol)
+    // For tag values, need transpose (lev, ncol) to (ncol, lev)
+    size_t ni = vdatas[i].readCounts[2]; // ncol
+    size_t nj = 1; // Here we should just set nj to 1
+    size_t nk = vdatas[i].readCounts[1]; // lev
+
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
+      // Tag data for this timestep
       void* data = vdatas[i].varDatas[t];
-      size_t ni = vdatas[i].readCounts[t][2];
-      size_t nj = 1; // For HOMME, nj holds # quads, so here should set to 1
-      size_t nk = vdatas[i].readCounts[t][1];
+
+      // Set readStart for each timestep along time dimension
+      vdatas[i].readStarts[0] = tstep_nums[t];
 
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
@@ -773,7 +784,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
           break;
         }
         case NC_DOUBLE: {
-          // Copy from float case
+          // Copied from float case
           std::vector<double> tmpdoubledata(sz);
 
           // In the case of ucd mesh, and on multiple proc,
@@ -781,9 +792,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
           // localGidVerts range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
-
-          // Assume that the last dimension is for the ncol, number of vertices
           size_t indexInDoubleArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
@@ -791,11 +799,11 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readStarts[t][nbDims - 1] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims - 1] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[2] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                            &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpdoubledata[indexInDoubleArray]));
             ERRORS(success, "Failed to read float data in loop");
             // We need to increment the index in double array for the
@@ -805,7 +813,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
           assert(ic == localGidVerts.psize());
 
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, ncol) to (ncol, lev)
             success = kji_to_jik_stride(ni, nj, nk, data, &tmpdoubledata[0], localGidVerts);
           else {
             for (std::size_t idx = 0; idx != tmpdoubledata.size(); idx++)
@@ -822,9 +830,6 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
           // localGidVerts range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
-
-          // Assume that the last dimension is for the ncol
           size_t indexInFloatArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = localGidVerts.pair_begin();
@@ -832,11 +837,11 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readStarts[t][nbDims-1] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims-1] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[2] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[2] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                            &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpfloatdata[indexInFloatArray]));
             ERRORS(success, "Failed to read float data in loop");
             // We need to increment the index in float array for the
@@ -846,7 +851,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData
           assert(ic == localGidVerts.psize());
 
           if (vdatas[i].numLev != 1)
-            // Switch from k varying slowest to k varying fastest
+            // Transpose (lev, ncol) to (ncol, lev)
             success = kji_to_jik_stride(ni, nj, nk, data, &tmpfloatdata[0], localGidVerts);
           else {
             for (std::size_t idx = 0; idx != tmpfloatdata.size(); idx++)

diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index c803bf3..684aa4d 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -147,12 +147,14 @@ ErrorCode NCHelperMPAS::init_mesh_vals()
 
   // Store time coordinate values in tVals
   if (nTimeSteps > 0) {
+    // Note, two possible types for xtime variable: double(Time) or char(Time, StrLen)
     if ((vmit = varInfo.find("xtime")) != varInfo.end() && (*vmit).second.varDims.size() == 1) {
+      // If xtime variable is double type, read time coordinate values to tVals
       rval = read_coordinate("xtime", 0, nTimeSteps - 1, tVals);
       ERRORR(rval, "Trouble reading 'xtime' variable.");
     }
     else {
-      // If expected time variable is not available, set dummy time coordinate values to tVals
+      // If xtime variable does not exist, or it is string type, set dummy values to tVals
       for (int t = 0; t < nTimeSteps; t++)
         tVals.push_back((double)t);
     }
@@ -548,62 +550,79 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
 #endif
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // Skip edge variables, if specified by the read options
     if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
       continue;
 
+    // Support non-set variables with 3 dimensions like (Time, nCells, nVertLevels), or
+    // 2 dimensions like (Time, nCells)
+    assert(3 == vdatas[i].varDims.size() || 2 == vdatas[i].varDims.size());
+
+    // For a non-set variable, time should be the first dimension
+    assert(tDim == vdatas[i].varDims[0]);
+
+    // Set up readStarts and readCounts
+    vdatas[i].readStarts.resize(3);
+    vdatas[i].readCounts.resize(3);
+
+    // First: Time
+    vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
+    vdatas[i].readCounts[0] = 1;
+
+    // Next: nVertices / nCells / nEdges
+    switch (vdatas[i].entLoc) {
+      case ReadNC::ENTLOCVERT:
+        // Vertices
+        // Start from the first localGidVerts
+        // Actually, this will be reset later on in a loop
+        vdatas[i].readStarts[1] = localGidVerts[0] - 1;
+        vdatas[i].readCounts[1] = nLocalVertices;
+        range = &verts;
+        break;
+      case ReadNC::ENTLOCFACE:
+        // Faces
+        // Start from the first localGidCells
+        // Actually, this will be reset later on in a loop
+        vdatas[i].readStarts[1] = localGidCells[0] - 1;
+        vdatas[i].readCounts[1] = nLocalCells;
+        range = &facesOwned;
+        break;
+      case ReadNC::ENTLOCEDGE:
+        // Edges
+        // Start from the first localGidEdges
+        // Actually, this will be reset later on in a loop
+        vdatas[i].readStarts[1] = localGidEdges[0] - 1;
+        vdatas[i].readCounts[1] = nLocalEdges;
+        range = &edges;
+        break;
+      default:
+        ERRORR(MB_FAILURE, "Unexpected entity location type for MPAS non-set variable.");
+        break;
+    }
+
+    // Finally: nVertLevels or other optional levels, it is possible that there
+    // is no level dimension for this non-set variable
+    vdatas[i].readStarts[2] = 0;
+    vdatas[i].readCounts[2] = vdatas[i].numLev;
+
+    // Get variable size
+    vdatas[i].sz = 1;
+    for (std::size_t idx = 0; idx != 3; idx++)
+      vdatas[i].sz *= vdatas[i].readCounts[idx];
+
     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]);
+
+      if (tstep_nums[t] >= dimLens[tDim]) {
+        ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for a timestep number.");
+      }
+
       // Get the tag to read into
       if (!vdatas[i].varTags[t]) {
         rval = get_tag_to_nonset(vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev);
         ERRORR(rval, "Trouble getting tag.");
       }
 
-      // Assume point-based values for now?
-      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) {
-        ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given for time-independent variable.");
-      }
-
-      // Set up the dimensions and counts
-      // First: Time
-      vdatas[i].readStarts[t].push_back(tstep_nums[t]);
-      vdatas[i].readCounts[t].push_back(1);
-
-      // Next: nCells or nEdges or nVertices
-      switch (vdatas[i].entLoc) {
-        case ReadNC::ENTLOCVERT:
-          // Vertices
-          vdatas[i].readStarts[t].push_back(localGidVerts[0] - 1);
-          vdatas[i].readCounts[t].push_back(nLocalVertices);
-          range = &verts;
-          break;
-        case ReadNC::ENTLOCFACE:
-          // Faces
-          vdatas[i].readStarts[t].push_back(localGidCells[0] - 1);
-          vdatas[i].readCounts[t].push_back(nLocalCells);
-          range = &facesOwned;
-          break;
-        case ReadNC::ENTLOCEDGE:
-          // Edges
-          vdatas[i].readStarts[t].push_back(localGidEdges[0] - 1);
-          vdatas[i].readCounts[t].push_back(nLocalEdges);
-          range = &edges;
-          break;
-        default:
-          ERRORR(MB_FAILURE, "Unexpected entity location type for MPAS non-set variable.");
-          break;
-      }
-
-      // Last, numLev, even if it is 1
-      vdatas[i].readStarts[t].push_back(0);
-      vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
-      // Some variables have no level dimension, e.g. surface_pressure(Time, nCells)
-      assert(vdatas[i].readStarts[t].size() == vdatas[i].varDims.size() ||
-             vdatas[i].readStarts[t].size() == vdatas[i].varDims.size() + 1);
-
       // Get ptr to tag space
       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
@@ -619,12 +638,6 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(std::vector<ReadNC:
         vdatas[i].varDatas[t] = data;
       }
     }
-
-    // Calculate variable size
-    std::size_t sz = 1;
-    for (std::size_t idx = 0; idx != vdatas[i].readCounts[0].size(); idx++)
-      sz *= vdatas[i].readCounts[0][idx];
-    vdatas[i].sz = sz;
   }
 
   return rval;
@@ -645,6 +658,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
   Range* pLocalGid = NULL;
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // Skip edge variables, if specified by the read options
     if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
       continue;
 
@@ -672,6 +686,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
       std::vector<int> requests(nb_reads), statuss(nb_reads);
       size_t idxReq = 0;
 
+      // Set readStart for each timestep along time dimension
+      vdatas[i].readStarts[0] = tstep_nums[t];
+
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         case NC_CHAR: {
@@ -686,9 +703,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
 
-          // Assume that the last dimension is for the nVertLevels
           size_t indexInDoubleArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = pLocalGid->pair_begin();
@@ -696,13 +711,13 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(std::vector<ReadNC::Va
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // inclusive
-            vdatas[i].readStarts[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims - 2] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[1] = (NCDF_SIZE) (endh - starth + 1);
 
             // Do a partial read, in each subrange
             // wait outside this loop
             success = NCFUNCREQG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpdoubledata[indexInDoubleArray]), &requests[idxReq++]);
             ERRORS(success, "Failed to read double data in loop");
             // We need to increment the index in double array for the
@@ -800,6 +815,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
   Range* pLocalGid = NULL;
 
   for (unsigned int i = 0; i < vdatas.size(); i++) {
+    // Skip edge variables, if specified by the read options
     if (noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE)
       continue;
 
@@ -821,6 +837,9 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
     std::size_t sz = vdatas[i].sz;
 
     for (unsigned int t = 0; t < tstep_nums.size(); t++) {
+      // Set readStart for each timestep along time dimension
+      vdatas[i].readStarts[0] = tstep_nums[t];
+
       switch (vdatas[i].varDataType) {
         case NC_BYTE:
         case NC_CHAR: {
@@ -828,7 +847,6 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
           break;
         }
         case NC_DOUBLE: {
-          // Copy from float case
           std::vector<double> tmpdoubledata(sz);
 
           // In the case of ucd mesh, and on multiple proc,
@@ -836,9 +854,6 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
           // localGid range;
           // basically, we have to give a different point
           // for data to start, for every subrange :(
-          size_t nbDims = vdatas[i].readStarts[t].size();
-
-          // Assume that the last dimension is for the nVertLevels
           size_t indexInDoubleArray = 0;
           size_t ic = 0;
           for (Range::pair_iterator pair_iter = pLocalGid->pair_begin();
@@ -846,11 +861,11 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(std::vector<ReadNC::VarData>
               pair_iter++, ic++) {
             EntityHandle starth = pair_iter->first;
             EntityHandle endh = pair_iter->second; // Inclusive
-            vdatas[i].readStarts[t][nbDims - 2] = (NCDF_SIZE) (starth - 1);
-            vdatas[i].readCounts[t][nbDims - 2] = (NCDF_SIZE) (endh - starth + 1);
+            vdatas[i].readStarts[1] = (NCDF_SIZE) (starth - 1);
+            vdatas[i].readCounts[1] = (NCDF_SIZE) (endh - starth + 1);
 
             success = NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
-                &(vdatas[i].readStarts[t][0]), &(vdatas[i].readCounts[t][0]),
+                &(vdatas[i].readStarts[0]), &(vdatas[i].readCounts[0]),
                             &(tmpdoubledata[indexInDoubleArray]));
             ERRORS(success, "Failed to read double data in loop");
             // We need to increment the index in double array for the

diff --git a/src/io/ReadCGM.cpp b/src/io/ReadCGM.cpp
index a610d4a..cc83c9b 100644
--- a/src/io/ReadCGM.cpp
+++ b/src/io/ReadCGM.cpp
@@ -16,6 +16,7 @@
 #pragma warning(disable:4786)
 #endif
 
+#include "cgm_version.h"
 #include "GeometryQueryTool.hpp"
 #include "ModelQueryEngine.hpp"
 #include "RefEntityName.hpp"
@@ -314,7 +315,11 @@ ErrorCode ReadCGM::load_file(const char *cgm_file_name,
 
     // create entity sets for all ref groups
   std::vector<Tag> extra_name_tags;
+#if  CGM_MAJOR_VERSION>13
+  DLIList<CubitString> name_list;
+#else
   DLIList<CubitString*> name_list;
+#endif
   entlist.clean_out();
   GeometryQueryTool::instance()->ref_entity_list( "group", entlist );
   entlist.reset();
@@ -325,7 +330,11 @@ ErrorCode ReadCGM::load_file(const char *cgm_file_name,
     if (name_list.size() == 0)
       continue;
     name_list.reset();
+#if  CGM_MAJOR_VERSION>13
+    CubitString name1 = name_list.get();
+#else
     CubitString name1 = *name_list.get();
+#endif
     
     EntityHandle h;
     rval = mdbImpl->create_meshset( MESHSET_SET, h );
@@ -361,7 +370,11 @@ ErrorCode ReadCGM::load_file(const char *cgm_file_name,
       }
         
       for (int j = 0; j < name_list.size(); ++j) {
+#if  CGM_MAJOR_VERSION>13
+        name1 = name_list.get_and_step();
+#else
         name1 = *name_list.get_and_step();
+#endif
         memset( namebuf, '\0', NAME_TAG_SIZE );
         strncpy( namebuf, name1.c_str(), NAME_TAG_SIZE - 1 );
         if (name1.length() >= (unsigned)NAME_TAG_SIZE)
@@ -461,7 +474,11 @@ ErrorCode ReadCGM::load_file(const char *cgm_file_name,
     RefEdge* edge = dynamic_cast<RefEdge*>(ci->first);
     Curve* curve = edge->get_curve_ptr();
     data.clean_out();
+#if  CGM_MAJOR_VERSION>12
+    edge->get_graphics( data, norm_tol, faceting_tol);
+#else
     edge->get_graphics( data, faceting_tol);
+#endif
     if (CUBIT_SUCCESS != s)
       return MB_FAILURE;
       

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/da43a46da51e/
Changeset:   da43a46da51e
Branch:      None
User:        danwu
Date:        2014-01-02 16:39:11
Summary:     Merged fathomteam/moab into master
Affected #:  13 files

diff --git a/doc/MetaData/metadata.h b/doc/MetaData/metadata.h
index 9bca8a6..1a26215 100644
--- a/doc/MetaData/metadata.h
+++ b/doc/MetaData/metadata.h
@@ -210,9 +210,11 @@ Create a gather set (associated with tag GATHER_SET) on one processor with the s
 
 <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.
+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.
+
+<H3>no_edges </H3>
+
+Indicates that no edges should be created and no edge variables will be read. This option can be used when there is no need to read variables on edges. For a huge MPAS file with 65M cells, it can save more than 3GB MOAB internal storage for edge connectivity.
 
 \ref md-contents "Top"
 

diff --git a/doc/metadata_info.doc b/doc/metadata_info.doc
index a143f91..70d273a 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 d86a470..144e5f8 100644
Binary files a/doc/metadata_info.pdf and b/doc/metadata_info.pdf differ

diff --git a/itaps/imesh/partest.cpp b/itaps/imesh/partest.cpp
index 0f46172..52ba517 100644
--- a/itaps/imesh/partest.cpp
+++ b/itaps/imesh/partest.cpp
@@ -1,4 +1,4 @@
-#include <iostream>
+
 #include <stdio.h>
 #include <string.h>
 #include "moab_mpi.h"
@@ -7,6 +7,8 @@
 
 #define IMESH_ASSERT(ierr) if (ierr!=0) printf("imesh assert\n");
 #define IMESH_NULL 0
+#define STRINGIFY_(X) #X
+#define STRINGIFY(X) STRINGIFY_(X)
 
 int main(int argc, char* argv[]){
   MPI_Init(&argc, &argv);
@@ -26,8 +28,11 @@ int main(int argc, char* argv[]){
   iMeshP_createPartitionAll(imesh, MPI_COMM_WORLD, &partn, &ierr);
   IMESH_ASSERT(ierr);
 
-  const char options[] = ";PARTITION=MATERIAL_SET";
-  const char filename[] = "64bricks_1mhex.h5m";
+  const char options[] = " moab:PARALLEL=READ_PART "
+                         " moab:PARTITION=PARALLEL_PARTITION "
+                         " moab:PARALLEL_RESOLVE_SHARED_ENTS "
+                         " moab:PARTITION_DISTRIBUTE ";
+  const char * filename = STRINGIFY(MESHDIR) "/64bricks_1khex.h5m";;
 
   iMeshP_loadAll(imesh,
               partn,

diff --git a/src/io/ReadCGM.cpp b/src/io/ReadCGM.cpp
index cc83c9b..bb9eb9a 100644
--- a/src/io/ReadCGM.cpp
+++ b/src/io/ReadCGM.cpp
@@ -326,16 +326,23 @@ ErrorCode ReadCGM::load_file(const char *cgm_file_name,
   for (int i = entlist.size(); i--; ) {
     RefEntity* grp = entlist.get_and_step();
     name_list.clean_out();
-    RefEntityName::instance()->get_refentity_name( grp, name_list, true );
+#if  CGM_MAJOR_VERSION>13
+    RefEntityName::instance()->get_refentity_name(grp, name_list);
+#else
+    //true argument is optional, but for large multi-names situation, it should save 
+    //some cpu time
+    RefEntityName::instance()->get_refentity_name(grp, name_list,true);
+#endif
     if (name_list.size() == 0)
       continue;
+
     name_list.reset();
 #if  CGM_MAJOR_VERSION>13
     CubitString name1 = name_list.get();
 #else
     CubitString name1 = *name_list.get();
 #endif
-    
+
     EntityHandle h;
     rval = mdbImpl->create_meshset( MESHSET_SET, h );
     if (MB_SUCCESS != rval)

diff --git a/src/io/Tqdcfr.cpp b/src/io/Tqdcfr.cpp
index 717f43a..2c0317b 100644
--- a/src/io/Tqdcfr.cpp
+++ b/src/io/Tqdcfr.cpp
@@ -49,6 +49,10 @@ static bool debug = false;
 //const int ACIS_DIMS[] = {-1, 3, -1, 2, -1, -1, 1, 0, -1, -1};
 const char Tqdcfr::geom_categories[][CATEGORY_TAG_SIZE] = 
 {"Vertex\0", "Curve\0", "Surface\0", "Volume\0"};
+
+// will be used in a static function, so declared outside class members :(
+// major/minor cubit version that wrote this file
+int major=-1, minor=-1;
 const EntityType Tqdcfr::group_type_to_mb_type[] = {
   MBENTITYSET, MBENTITYSET, MBENTITYSET, // group, body, volume
   MBENTITYSET, MBENTITYSET, MBENTITYSET, // surface, curve, vertex
@@ -316,7 +320,7 @@ ErrorCode Tqdcfr::load_file(const char *file_name,
   else data_version = modelMetaData.metadataEntries[md_index].mdDblValue;
   
     // get the major/minor cubit version that wrote this file
-  int major = -1, minor = -1;
+//  int major = -1, minor = -1;
   md_index = modelMetaData.get_md_entry(2, "CubitVersion");
   if (md_index >= 0 && !modelMetaData.metadataEntries[md_index].mdStringValue.empty())
     sscanf( modelMetaData.metadataEntries[md_index].mdStringValue.c_str(), "%d.%d",
@@ -1501,7 +1505,8 @@ ErrorCode Tqdcfr::read_elements(Tqdcfr::ModelEntry *model,
 
       // get the connectivity array
     unsigned int total_conn = num_elem * nodes_per_elem;
-    
+    if(major >=14)
+      FREADI(num_elem);// we need to skip num_elem in advance, it looks like
     FREADI(total_conn);
 
       // post-process connectivity into handles
@@ -1825,7 +1830,12 @@ ErrorCode Tqdcfr::GeomHeader::read_info_header(const unsigned int model_offset,
       geom_headers[i].maxDim = std::max(geom_headers[i].maxDim, 
                                         (int)CN::Dimension(elem_type));
       if (j < geom_headers[i].elemTypeCt-1) 
-        instance->FREADI(num_elem + num_elem*nodes_per_elem);
+      {
+        int num_skipped_ints = num_elem + num_elem*nodes_per_elem;
+        if (major>=14)
+          num_skipped_ints+=num_elem;
+        instance->FREADI(num_skipped_ints);
+      }
     }
     
   }

diff --git a/test/io/stl_test.cc b/test/io/stl_test.cc
index d2a448a..8956b38 100644
--- a/test/io/stl_test.cc
+++ b/test/io/stl_test.cc
@@ -17,7 +17,8 @@ static const char sample[] = STRINGIFY(MESHDIR) "/io/sample.stl";
 static const char sample[] = "sample.stl";
 #endif
 
-const char* tmp_file = "test.stl";
+// Use static keyword so that tmp_file can only be accessed within this file
+static const char* tmp_file = "test.stl";
 
 void test_read_ascii();
 void test_write_ascii();

diff --git a/tools/mbcslam/Intx2Mesh.cpp b/tools/mbcslam/Intx2Mesh.cpp
index 74f65ff..416315e 100644
--- a/tools/mbcslam/Intx2Mesh.cpp
+++ b/tools/mbcslam/Intx2Mesh.cpp
@@ -1164,6 +1164,13 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
   std::string tag_name("DP");
   rval = mb->tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE);
   ERRORR(rval, "can't get DP tag");
+
+  EntityHandle dum=0;
+  Tag corrTag;
+  rval = mb->tag_get_handle(CORRTAGNAME,
+                                           1, MB_TYPE_HANDLE, corrTag,
+                                           MB_TAG_DENSE|MB_TAG_CREAT, &dum);
+  ERRORR(rval, "can't get CORR tag");
   // get all local verts
   Range local_verts;
   rval = mb->get_connectivity(localEnts, local_verts);
@@ -1245,7 +1252,7 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
   TLv.enableWriteAccess();
 
   int sizeTuple = 2+max_edges; // determined earlier
-  TLq.initialize(2+max_edges, 0, 0, 0, numq); // to proc, elem GLOBAL ID, connectivity[10] (global ID v)
+  TLq.initialize(2+max_edges, 0, 1, 0, numq); // to proc, elem GLOBAL ID, connectivity[10] (global ID v), local eh
   TLq.enableWriteAccess();
   std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n";
 
@@ -1295,6 +1302,8 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
       {
         TLq.vi_wr[sizeTuple*n+2+k] = 0; // fill the rest of node ids with 0; we know that the node ids start from 1!
       }
+      TLq.vul_wr[n]=q; // save here the entity handle, it will be communicated back
+      // mabe we should forget about global ID
       TLq.inc_n();
 
     }
@@ -1372,12 +1381,23 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
     rval=mb->tag_get_data(gid, &q, 1, &gid_el);
     ERRORR(rval, "can't get element global ID ");
     globalID_to_eh[gid_el]=new_element;
+    // is this redundant or not?
+    rval = mb->tag_set_data(corrTag, &new_element, 1, &q);
+    ERRORR(rval, "can't set corr tag on new el");
+    // set the global id on new elem
+    rval = mb->tag_set_data(gid, &new_element, 1, &gid_el);
+    ERRORR(rval, "can't set global id tag on new el");
   }
   // now look at all elements received through; we do not want to duplicate them
   n=TLq.get_n();// number of elements received by this processor
+  // form the remote cells, that will be used to send the tracer info back to the originating proc
+  remote_cells = new TupleList();
+  remote_cells->initialize(2, 0, 1, 1, n);
+  remote_cells->enableWriteAccess();
   for (int i=0; i<n; i++)
   {
     int globalIdEl = TLq.vi_rd[sizeTuple*i+1];
+    int from_proc =  TLq.vi_wr[sizeTuple*i];
     // do we already have a quad with this global ID, represented?
     if (globalID_to_eh.find(globalIdEl)==globalID_to_eh.end())
     {
@@ -1408,6 +1428,16 @@ ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg(EntityHandle & euler_set, Ent
       globalID_to_eh[globalIdEl]=new_element;
       rval = mb->add_entities(covering_lagr_set, &new_element, 1);
       ERRORR(rval, "can't add new element to dep set");
+     /* rval = mb->tag_set_data(corrTag, &new_element, 1, &q);
+      ERRORR(rval, "can't set corr tag on new el");*/
+      remote_cells->vi_wr[2*i]=from_proc;
+      remote_cells->vi_wr[2*i+1]=globalIdEl;
+      remote_cells->vr_wr[i] = 0.; // no contribution yet sent back
+      remote_cells->vul_wr[i]= TLq.vul_rd[i];// this is the corresponding red cell (arrival)
+      remote_cells->inc_n();
+      // set the global id on new elem
+      rval = mb->tag_set_data(gid, &new_element, 1, &globalIdEl);
+      ERRORR(rval, "can't set global id tag on new el");
     }
   }
   return MB_SUCCESS;

diff --git a/tools/mbcslam/Makefile.am b/tools/mbcslam/Makefile.am
index 9138c7a..766c8ab 100644
--- a/tools/mbcslam/Makefile.am
+++ b/tools/mbcslam/Makefile.am
@@ -24,7 +24,7 @@ LDADD = $(top_builddir)/src/libMOAB.la libmbcslam.la
 
 libmbcslam_la_SOURCES = \
    Intx2Mesh.cpp Intx2Mesh.hpp Intx2MeshOnSphere.cpp Intx2MeshOnSphere.hpp \
-     CslamUtils.cpp CslamUtils.hpp Intx2MeshInPlane.cpp Intx2MeshInPlane.hpp 
+     CslamUtils.cpp CslamUtils.hpp Intx2MeshInPlane.cpp Intx2MeshInPlane.hpp wrap_intx.cpp 
 
 # these will be installed
 libmbcslam_la_include_HEADERS = 
@@ -39,7 +39,7 @@ cfgdir = $(libdir)
 
 TESTS = intx_on_sphere_test  intx_in_plane_test spherical_area_test \
          case1_test  intx_mpas
-noinst_PROGRAMS =  cslam_par_test diffusion proj1 
+noinst_PROGRAMS =  cslam_par_test diffusion proj1 intx_imesh create_dp advection
 
 check_PROGRAMS = $(TESTS) 
 intx_on_sphere_test_SOURCES = intx_on_sphere_test.cpp
@@ -51,6 +51,9 @@ case1_test_SOURCES = case1_test.cpp
 intx_mpas_SOURCES = intx_mpas.cpp
 cslam_par_test_SOURCES = cslam_par_test.cpp
 proj1_SOURCES = proj1.cpp
+intx_imesh_SOURCES = intx_imesh.cpp
+create_dp_SOURCES = create_dp.cpp
+advection_SOURCES = advection.F90
 
 EXTRA_DIST  = lagrangeHomme.vtk  \
               eulerHomme.vtk \

diff --git a/tools/mbcslam/advection.F90 b/tools/mbcslam/advection.F90
new file mode 100644
index 0000000..fb102ba
--- /dev/null
+++ b/tools/mbcslam/advection.F90
@@ -0,0 +1,122 @@
+! advection: do a one time step transport, using c binding module
+!            example of how to do it in parallel in fortran
+! This program shows how to load in parallel in moab from Fortran90, and how
+!   to call the transport wrapper. It is a fortran equivalent of intx_imesh
+!   driver
+!
+! Usage: advection
+
+#define CHECK(a)   if (ierr .ne. 0) print *, a
+program advection
+
+  use ISO_C_BINDING
+  implicit none
+
+#include "mpif.h"
+
+#ifdef USE_MPI
+#  include "iMeshP_f.h"
+#else
+#  include "iMesh_f.h"
+#endif
+
+! extern void update_tracer( iMesh_Instance instance,  iBase_EntitySetHandle * opEulerSet, int * ierr);
+  INTERFACE
+   SUBROUTINE update_tracer ( instance , opEulerSet, ierr) bind(C)
+     use ISO_C_BINDING
+     implicit none
+     iMesh_Instance, INTENT(IN) , VALUE :: instance
+     iBase_EntityHandle, INTENT(OUT) :: opEulerSet
+     integer(c_int) , INTENT (OUT) :: ierr
+   END SUBROUTINE update_tracer
+  END INTERFACE
+
+  ! declarations
+  ! imesh is the instance handle
+  iMesh_Instance imesh
+
+  ! ents, verts will be arrays storing vertex/entity handles
+  iBase_EntityHandle, pointer :: ents, verts
+  iBase_EntitySetHandle root_set
+  iBase_EntitySetHandle opEulerSet
+  CHARACTER (LEN=200) options
+  CHARACTER (LEN=200) filename
+  CHARACTER (LEN=200) optionswrite
+  CHARACTER (LEN=200) outname
+  TYPE(C_PTR) :: vertsPtr, entsPtr
+
+  integer rank, sz, ierr
+  integer lenopt, lenname
+
+#ifdef USE_MPI
+  ! local variables for parallel runs
+  iMeshP_PartitionHandle imeshp
+  IBASE_HANDLE_T mpi_comm_c
+#endif
+
+  ! init the parallel partition
+  call MPI_INIT(ierr)
+  CHECK("fail to initialize MPI")
+  call MPI_COMM_SIZE(MPI_COMM_WORLD, sz, ierr)
+  CHECK("fail to get MPI size")
+  call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
+  CHECK("fail to get MPI rank")
+
+  ! now load the mesh; this also initializes parallel sharing
+  imesh = 0
+  imeshp = 0
+  call iMesh_newMesh("MOAB", imesh, ierr)
+  CHECK("fail to initialize imesh")
+
+  call iMesh_getRootSet(%VAL(imesh), root_set, ierr)
+  CHECK("fail to get root set")
+
+  call iMeshP_getCommunicator(%VAL(imesh), MPI_COMM_WORLD, mpi_comm_c, ierr)
+
+  call iMeshP_createPartitionAll(%VAL(imesh), %VAL(mpi_comm_c), imeshp, ierr)
+  CHECK("fail to create parallel partition ")
+  options = " moab:PARALLEL=READ_PART moab:PARTITION=PARALLEL_PARTITION" // &
+            " moab:PARALLEL_RESOLVE_SHARED_ENTS moab:PARTITION_DISTRIBUTE "
+!            " moab:PARALLEL=READ_PART moab:PARTITION=PARALLEL_PARTITION " &
+!              " moab:PARALLEL_RESOLVE_SHARED_ENTS moab:PARTITION_DISTRIBUTE ", & ! options
+  if (0 .eq. rank) then
+    print *, "load in parallel file HN16DP.h5m"
+  endif
+  lenname = 11;
+  lenopt = 123
+  filename = "HN16DP.h5m"
+  call iMeshP_loadAll(%VAL(imesh), &
+              %VAL(imeshp), &
+              %VAL(root_set), &
+              filename, & ! filename
+              options, & !options
+              ierr, &
+              %VAL(lenname), & ! strlen(filename),
+              %VAL(lenopt) )  !119) !strlen(options));
+  CHECK("fail to load mesh in parallel ")
+
+  call update_tracer(imesh, opEulerSet, ierr)
+  CHECK("fail to update tracer ")
+
+  outname = "outF.h5m";
+  optionswrite = " moab:PARALLEL=WRITE_PART " ;
+  lenname = 8
+  lenopt = 27
+  call iMeshP_saveAll( %VAL(imesh), &
+              %VAL(imeshp), &
+               %VAL(opEulerSet), &
+               outname, &
+               optionswrite, &
+               ierr, &
+               %VAL(lenname), &  ! strlen(filename),
+               %VAL(lenopt) )   !119) !strlen(options));
+  CHECK(" can't save ")
+
+  if (0==rank) then
+    print *, "Done"
+  endif
+
+  call MPI_FINALIZE(ierr)
+  stop
+end program advection
+

diff --git a/tools/mbcslam/create_dp.cpp b/tools/mbcslam/create_dp.cpp
new file mode 100644
index 0000000..bd2459b
--- /dev/null
+++ b/tools/mbcslam/create_dp.cpp
@@ -0,0 +1,273 @@
+/*
+ * create_dp.cpp
+ *
+ *  Created on: Dec 12, 2013
+ *  just to add a "DP" tag to an already partitioned mesh, based on some formula
+ *  it is launched in serial
+ */
+#include "moab/Core.hpp"
+#include "moab/Interface.hpp"
+#include <iostream>
+#include <math.h>
+#include <TestUtil.hpp>
+
+#include "CslamUtils.hpp"
+#include <assert.h>
+using namespace moab;
+
+double radius = 1.;// in m:  6371220.
+int field_type = 1;
+
+ErrorCode add_field_value(Interface & mb)
+{
+  ErrorCode rval = MB_SUCCESS;
+
+  Tag tagTracer = 0;
+  std::string tag_name("Tracer");
+  rval = mb.tag_get_handle(tag_name.c_str(), 1, MB_TYPE_DOUBLE, tagTracer, MB_TAG_DENSE | MB_TAG_CREAT);
+  CHECK_ERR(rval);
+
+  // tagElem is the average computed at each element, from nodal values
+  Tag tagElem = 0;
+  std::string tag_name2("TracerAverage");
+  rval = mb.tag_get_handle(tag_name2.c_str(), 1, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT);
+  CHECK_ERR(rval);
+
+  Tag tagArea = 0;
+  std::string tag_name4("Area");
+  rval = mb.tag_get_handle(tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT);
+  CHECK_ERR(rval);
+
+  /*
+   * get all plys first, then vertices, then move them on the surface of the sphere
+   *  radius is 1., most of the time
+   *
+   */
+  Range polygons;
+  rval = mb.get_entities_by_dimension(0, 2, polygons);
+  if (MB_SUCCESS != rval)
+    return rval;
+
+  Range connecVerts;
+  rval = mb.get_connectivity(polygons, connecVerts);
+  if (MB_SUCCESS != rval)
+    return rval;
+
+
+
+  void *data; // pointer to the LOC in memory, for each vertex
+  int count;
+
+  rval = mb.tag_iterate(tagTracer, connecVerts.begin(), connecVerts.end(), count, data);
+  CHECK_ERR(rval);
+  // here we are checking contiguity
+  assert(count == (int) connecVerts.size());
+  double * ptr_DP=(double*)data;
+  // lambda is for longitude, theta for latitude
+   // param will be: (la1, te1), (la2, te2), b, c; hmax=1, r=1/2
+  // nondivergent flow, page 5, case 1, (la1, te1) = (M_PI, M_PI/3)
+  //                                    (la2, te2) = (M_PI, -M_PI/3)
+  //                 la1,    te1    la2    te2     b     c  hmax  r
+  if (field_type==1) // quasi smooth
+  {
+    double params[] = { M_PI, M_PI/3, M_PI, -M_PI/3, 0.1, 0.9, 1., 0.5};
+    for (Range::iterator vit=connecVerts.begin();vit!=connecVerts.end(); vit++ )
+    {
+      EntityHandle oldV=*vit;
+      CartVect posi;
+      rval = mb.get_coords(&oldV, 1, &(posi[0]) );
+      CHECK_ERR(rval);
+
+      SphereCoords sphCoord = cart_to_spherical(posi);
+
+      ptr_DP[0]=quasi_smooth_field(sphCoord.lon, sphCoord.lat, params);;
+
+      ptr_DP++; // increment to the next node
+    }
+  }
+  else if (2 == field_type) // smooth
+  {
+    CartVect p1, p2;
+    SphereCoords spr;
+    spr.R = 1;
+    spr.lat = M_PI/3;
+    spr.lon= M_PI;
+    p1 = spherical_to_cart(spr);
+    spr.lat = -M_PI/3;
+    p2 = spherical_to_cart(spr);
+    //                  x1,    y1,     z1,    x2,   y2,    z2,   h_max, b0
+    double params[] = { p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], 1,    5.};
+    for (Range::iterator vit=connecVerts.begin();vit!=connecVerts.end(); vit++ )
+    {
+      EntityHandle oldV=*vit;
+      CartVect posi;
+      rval = mb.get_coords(&oldV, 1, &(posi[0]) );
+      CHECK_ERR(rval);
+
+      SphereCoords sphCoord = cart_to_spherical(posi);
+
+      ptr_DP[0]=smooth_field(sphCoord.lon, sphCoord.lat, params);;
+
+      ptr_DP++; // increment to the next node
+    }
+  }
+  else if (3 == field_type) // slotted
+  {
+    //                   la1, te1,   la2, te2,       b,   c,   r
+    double params[] = { M_PI, M_PI/3, M_PI, -M_PI/3, 0.1, 0.9, 0.5};// no h_max
+    for (Range::iterator vit=connecVerts.begin();vit!=connecVerts.end(); vit++ )
+    {
+      EntityHandle oldV=*vit;
+      CartVect posi;
+      rval = mb.get_coords(&oldV, 1, &(posi[0]) );
+      CHECK_ERR(rval);
+
+      SphereCoords sphCoord = cart_to_spherical(posi);
+
+      ptr_DP[0]=slotted_cylinder_field(sphCoord.lon, sphCoord.lat, params);;
+
+      ptr_DP++; // increment to the next node
+    }
+  }
+
+  // add average value for quad/polygon (average corners)
+  // do some averages
+
+
+  Range::iterator iter = polygons.begin();
+  double local_mass = 0.; // this is total mass on one proc
+  while (iter != polygons.end())
+  {
+    rval = mb.tag_iterate(tagElem, iter, polygons.end(), count, data);
+    CHECK_ERR(rval);
+    double * ptr=(double*)data;
+
+    rval = mb.tag_iterate(tagArea, iter, polygons.end(), count, data);
+    CHECK_ERR(rval);
+    double * ptrArea=(double*)data;
+    for (int i=0; i<count; i++, iter++, ptr++, ptrArea++)
+    {
+      const moab::EntityHandle * conn = NULL;
+      int num_nodes = 0;
+      rval = mb.get_connectivity(*iter, conn, num_nodes);
+      CHECK_ERR(rval);
+      if (num_nodes==0)
+        return MB_FAILURE;
+      std::vector<double> nodeVals(num_nodes);
+      double average=0.;
+      rval = mb.tag_get_data(tagTracer, conn, num_nodes, &nodeVals[0] );
+      CHECK_ERR(rval);
+      for (int j=0; j<num_nodes; j++)
+        average+=nodeVals[j];
+      average/=num_nodes;
+      *ptr = average;
+
+      // now get area
+      std::vector<double> coords;
+      coords.resize(3*num_nodes);
+      rval = mb.get_coords(conn, num_nodes, &coords[0]);
+      CHECK_ERR(rval);
+      *ptrArea =  area_spherical_polygon_lHuiller (&coords[0], num_nodes, radius);
+
+      // we should have used some
+      // total mass:
+      local_mass += *ptrArea * average;
+    }
+
+  }
+
+  // now we can delete the tags? not yet
+  return MB_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+
+  if (argc < 3)
+  {
+    std::cout << " usage: create_dp <input><output> -t <time>  -dt <delta_t> -h \n";
+    return 1;
+  }
+
+  double dt=0.1;
+  double t=0.1; // corresponding to diffusion first step
+
+  int index = 2;
+  char * input_mesh1 = argv[1];
+  char * output = argv[2];
+  while (index < argc)
+  {
+    if (!strcmp(argv[index], "-t")) // this is for radius to project
+    {
+      t = atof(argv[++index]);
+    }
+    if (!strcmp(argv[index], "-dt")) // delete partition sets
+    {
+      dt = atof(argv[++index]);
+    }
+
+    if (!strcmp(argv[index], "-h"))
+    {
+      std::cout << " usage: create_dp <input><output> -t <time>  -dt <delta_t> -h \n";
+      return 1;
+    }
+    index++;
+  }
+
+  Core moab;
+  Interface & mb = moab;
+
+  ErrorCode rval;
+
+  rval = mb.load_mesh(input_mesh1);
+
+  std::cout  << " -t " << t <<  " -dt " << dt << " input: " << input_mesh1 <<
+      "  output: " << output << "\n";
+
+  Range verts;
+  rval = mb.get_entities_by_dimension(0, 0, verts);
+  if (MB_SUCCESS != rval)
+    return 1;
+
+  double *x_ptr, *y_ptr, *z_ptr;
+  int count;
+  rval = mb.coords_iterate(verts.begin(), verts.end(), x_ptr, y_ptr, z_ptr, count);
+  if (MB_SUCCESS != rval)
+      return 1;
+  assert(count == (int) verts.size()); // should end up with just one contiguous chunk of vertices
+
+  Tag tagh = 0;
+  std::string tag_name("DP");
+  rval = mb.tag_get_handle(tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT);
+  CHECK_ERR(rval);
+  void *data; // pointer to the LOC in memory, for each vertex
+  int count_tag;
+
+  rval = mb.tag_iterate(tagh, verts.begin(), verts.end(), count_tag, data);
+  CHECK_ERR(rval);
+  // here we are checking contiguity
+  assert(count_tag == (int) verts.size());
+  double * ptr_DP=(double*)data;
+
+  for (int v = 0; v < count; v++) {
+     //EntityHandle v = verts[v];
+     CartVect pos( x_ptr[v], y_ptr[v] , z_ptr[v]);
+     CartVect newPos;
+     departure_point_case1(pos, t, dt, newPos);
+     ptr_DP[0]=newPos[0];
+     ptr_DP[1]=newPos[1];
+     ptr_DP[2]=newPos[2];
+     ptr_DP+=3; // increment to the next vertex
+  }
+
+
+  rval = add_field_value(mb);
+
+  mb.write_file(output);
+
+  return 0;
+}
+
+
+
+

diff --git a/tools/mbcslam/intx_imesh.cpp b/tools/mbcslam/intx_imesh.cpp
new file mode 100644
index 0000000..0c49ac4
--- /dev/null
+++ b/tools/mbcslam/intx_imesh.cpp
@@ -0,0 +1,92 @@
+
+/*
+ *  This program updates a manufactured tracer field from time T0 to time T1, in parallel.
+ *  Input: arrival mesh, already distributed on processors, and a departure position for
+ *  each vertex, saved in a tag DP
+ */
+#include <stdio.h>
+#include <string.h>
+#include "moab_mpi.h"
+#include "iMeshP.h"
+
+
+#define IMESH_ASSERT(ierr) if (ierr!=0) printf("imesh assert\n");
+#define IMESH_NULL 0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void update_tracer( iMesh_Instance instance,  iBase_EntitySetHandle * opEulerSet, int * ierr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+int main(int argc, char* argv[]){
+  MPI_Init(&argc, &argv);
+
+  iMesh_Instance imesh;
+  iMeshP_PartitionHandle partn;
+  int ierr, num_sets;
+
+  iBase_EntitySetHandle root;
+  imesh = IMESH_NULL;
+  iMesh_newMesh(0, &imesh, &ierr, 0);
+  IMESH_ASSERT(ierr);
+  iMesh_getRootSet( imesh, &root, &ierr );
+  IMESH_ASSERT(ierr);
+
+  iMeshP_createPartitionAll(imesh, MPI_COMM_WORLD, &partn, &ierr);
+  int rank, size;
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  MPI_Comm_size(MPI_COMM_WORLD, &size);
+  IMESH_ASSERT(ierr);
+
+  const char options[] = " moab:PARALLEL=READ_PART "
+                         " moab:PARTITION=PARALLEL_PARTITION "
+                         " moab:PARALLEL_RESOLVE_SHARED_ENTS "
+                         " moab:PARTITION_DISTRIBUTE ";
+  const char * filename = "HN16DP.h5m"; // the file should have the dp tag already
+
+  if (0==rank)
+    printf("load in parallel the file: %s \n", filename);
+  iMeshP_loadAll(imesh,
+              partn,
+              root,
+              filename,
+              options,
+              &ierr,
+              strlen(filename),
+              strlen(options));
+  IMESH_ASSERT(ierr);
+
+
+  iMesh_getNumEntSets(imesh,
+                      IMESH_NULL,
+                      1,
+                      &num_sets,
+                      &ierr);
+  IMESH_ASSERT(ierr);
+  printf("There's %d entity sets here on process rank %d \n", num_sets, rank);
+
+  iBase_EntitySetHandle euler_set;
+  update_tracer( imesh, &euler_set, &ierr);
+  IMESH_ASSERT(ierr);
+
+  // write everything
+  const char * out_name = "out.h5m";
+  const char optionswrite[] = " moab:PARALLEL=WRITE_PART " ;
+  iMeshP_saveAll( imesh, partn, euler_set,
+                     out_name,
+                     optionswrite,
+                     &ierr,
+                     strlen(out_name),
+                     strlen(optionswrite));
+  IMESH_ASSERT(ierr);
+
+  if (0==rank)
+    printf("Done\n");
+  MPI_Finalize(); //probably the 4th time this is called.. no big deal
+
+}

diff --git a/tools/mbcslam/wrap_intx.cpp b/tools/mbcslam/wrap_intx.cpp
new file mode 100644
index 0000000..e38c897
--- /dev/null
+++ b/tools/mbcslam/wrap_intx.cpp
@@ -0,0 +1,104 @@
+/*
+ * wrap_intx.cpp
+ *  Will implement the intersection method that will be callable from fortran too
+ *  will be added to the library mbcslam.a
+ *
+ *
+ *  Created on: Dec 14, 2013
+ *      Author: iulian
+ */
+#include "iMesh.h"
+#include "iMeshP.h"
+#include "MBiMesh.hpp"
+#include "moab/Core.hpp"
+#include "moab/Range.hpp"
+#include "Intx2MeshOnSphere.hpp"
+
+using namespace moab;
+double radius = 1.;
+double gtol = 1.e-9;
+bool debug = false;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void update_tracer( iMesh_Instance instance, iBase_EntitySetHandle * opEulerSet, int * ierr)
+{
+  Range ents;
+  moab::Interface * mb =MOABI;
+  *ierr =1;
+  ErrorCode rval = mb->get_entities_by_dimension(0, 2, ents);// root 0
+
+  ERRORV(rval,  "can't get all 2d entities from root");
+
+  EntityHandle euler_set;
+  //EntityHandle lagr_set;
+
+  rval = mb->create_meshset(MESHSET_SET, euler_set);
+  ERRORV(rval , "can't create arrival mesh set");
+
+  *opEulerSet = (iBase_EntitySetHandle)euler_set;
+
+  rval = mb->add_entities(euler_set, ents);
+  ERRORV(rval , "can't add ents to arrival set");
+
+  Intx2MeshOnSphere worker(mb);
+  worker.SetRadius(radius);
+
+  worker.SetErrorTolerance(gtol);
+
+  EntityHandle covering_lagr_set;
+  rval = mb->create_meshset(MESHSET_SET, covering_lagr_set);
+  ERRORV(rval , "can't create covering set ");
+
+  // we need to update the correlation tag and remote tuples
+  rval = worker.create_departure_mesh_2nd_alg(euler_set, covering_lagr_set);
+  ERRORV(rval , "can't populate covering set ");
+
+  if (debug)
+  {
+    rval = mb->write_file("lagr.h5m", 0, 0, &covering_lagr_set, 1  );
+    ERRORV(rval , "can't write covering set ");
+  }
+
+  EntityHandle outputSet;
+  rval = mb->create_meshset(MESHSET_SET, outputSet);
+  ERRORV(rval , "can't create output set ");
+
+  rval = worker.intersect_meshes(covering_lagr_set, euler_set, outputSet);
+  ERRORV(rval , "can't intersect ");
+
+  if (debug)
+  {
+    rval = mb->write_file("output.vtk", 0, 0, &outputSet, 1  );
+    ERRORV(rval , "can't write covering set ");
+  }
+
+  // tagElem is the average computed at each element, from nodal values
+  Tag tagElem = 0;
+  std::string tag_name2("TracerAverage");
+  rval = mb->tag_get_handle(tag_name2.c_str(), 1, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT);
+  ERRORV(rval , "can't get tracer tag ");
+
+  // area of the euler element is fixed, store it; it is used to recompute the averages at each
+  // time step
+  Tag tagArea = 0;
+  std::string tag_name4("Area");
+  rval = mb->tag_get_handle(tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT);
+  ERRORV(rval , "can't get area tag");
+
+  rval = worker.update_tracer_data(outputSet, tagElem, tagArea);
+  ERRORV(rval , "can't update tracer ");
+
+  // everything can be deleted now from intx data; polygons, etc.
+
+  *ierr = 0;
+  return;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+


https://bitbucket.org/fathomteam/moab/commits/cb959e0c4785/
Changeset:   cb959e0c4785
Branch:      None
User:        danwu
Date:        2014-01-08 16:46:45
Summary:     Merged fathomteam/moab into master
Affected #:  65 files

diff --git a/.gitignore b/.gitignore
index e824a6b..d842c2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -165,6 +165,7 @@ test/io/vtk_test
 test/kd_tree_test
 test/kd_tree_time
 test/kd_tree_tool
+test/lloyd_smoother_test
 test/mbcn_test
 test/mbfacet_test
 test/mbground_test

diff --git a/MeshFiles/unittest/Makefile.am b/MeshFiles/unittest/Makefile.am
index a1784ee..ab3e23e 100644
--- a/MeshFiles/unittest/Makefile.am
+++ b/MeshFiles/unittest/Makefile.am
@@ -33,5 +33,6 @@ EXTRA_DIST  = 125hex.g \
               poly14.txt \
               BedCrop2.h5m \
               mpas_p8.h5m \
-              Homme_2pt.h5m
+              Homme_2pt.h5m \
+              surfrandomtris-4part.h5m
 

diff --git a/examples/DeformMeshRemap.cpp b/examples/DeformMeshRemap.cpp
new file mode 100644
index 0000000..5442d1d
--- /dev/null
+++ b/examples/DeformMeshRemap.cpp
@@ -0,0 +1,488 @@
+/** @example DeformMeshRemap.cpp
+ * Description: Account for mesh deformation of a solid due to structural mechanics\n
+ * In this example there are two meshes, a "master" and "slave" mesh.  In the master mesh,
+ * the solid material is deformed, to mimic what happens when a solid heats up and deforms.
+ * The fluid mesh is smoothed to account for those deformations, and tags on the fluid are
+ * remapped to those new positions.  Then mesh positions and state variables are transferred
+ * to the slave mesh, mimicing another mesh used by some other physics.
+ *
+ * To run: ./DeformMeshRemap [<master_meshfile><slave_meshfile>]\n
+ * (default values can run if users don't specify the mesh files)
+ */
+
+#include "moab/Core.hpp"
+#include "moab/Range.hpp"
+#include "moab/LloydSmoother.hpp"
+#include "moab/ProgOptions.hpp"
+#include "moab/BoundBox.hpp"
+#include "moab/SpatialLocator.hpp"
+#include "MBTagConventions.hpp"
+#include "DataCoupler.hpp"
+
+#ifdef USE_MPI
+#  include "moab/ParallelComm.hpp"
+#endif
+
+#include <iostream>
+#include <set>
+#include <sstream>
+#include <assert.h>
+
+using namespace moab;
+using namespace std;
+
+#ifndef MESH_DIR
+#define MESH_DIR "."
+#endif
+
+ErrorCode read_file(string &fname, EntityHandle &seth, 
+                    Range &solids, Range &solid_elems, Range &fluids, Range &fluid_elems);
+void deform_func(const BoundBox &bbox, double *xold, double *xnew);
+ErrorCode deform_master(Range &fluid_elems, Range &solid_elems, Tag &xnew);
+ErrorCode smooth_master(int dim, Tag xnew, EntityHandle &master, Range &fluids);
+ErrorCode write_to_coords(Range &elems, Tag tagh);
+
+const int SOLID_SETNO = 100, FLUID_SETNO = 200;
+
+Interface *mb;
+#define RR(a) if (MB_SUCCESS != rval) {cout << a << endl; return MB_FAILURE;}
+
+const bool debug = true;
+
+class DeformMeshRemap 
+{
+public:
+
+    //! enumerator for solid/fluid, master/slave
+  enum {MASTER=0, SLAVE, SOLID, FLUID};
+  
+    //! constructor
+    //! if master is NULL, the MOAB part is run in serial; 
+    //! if slave is NULL but the master isn't, the slave is copied from the master
+    //! Create communicators using moab::ParallelComm::get_pcomm
+  DeformMeshRemap(Interface *impl, ParallelComm *master = NULL, ParallelComm *slave = NULL);
+  
+    //! destructor
+  ~DeformMeshRemap();
+
+    //! execute the deformed mesh process
+  ErrorCode execute();
+  
+    //! add a set number
+  ErrorCode add_set_no(int fluid_or_solid, int set_no);
+  
+    //! remove a set number
+  ErrorCode remove_set_no(int fluid_or_solid, int set_no);
+  
+    //! get the set numbers
+  ErrorCode get_set_nos(int fluid_or_solid, std::set<int> &set_nos) const;
+
+    //! get the xNew tag handle
+  inline Tag x_new() const {return xNew;}
+
+    //! get the tag name
+  std::string x_new_name() const {return xNewName;}
+  
+    //! set the tag name
+  void x_new_name(const std::string &name) {xNewName = name;}
+
+    //! get/set the file name
+  std::string get_file_name(int m_or_s) const;
+  
+    //! get/set the file name
+  void set_file_name(int m_or_s, const std::string &name);
+  
+private:
+    //! apply a known deformation to the solid elements, putting the results in the xNew tag; also
+    //! write current coordinates to the xNew tag for fluid elements
+  ErrorCode deform_master(Range &fluid_elems, Range &solid_elems, const char *tag_name = NULL);
+
+    //! read a file and establish proper ranges
+  ErrorCode read_file(int m_or_s, string &fname, EntityHandle &seth);
+
+    //! write the input tag to the coordinates for the vertices in the input elems
+  ErrorCode write_to_coords(Range &elems, Tag tagh);
+
+    //! write the tag to the vertices, then save to the specified file
+  ErrorCode write_and_save(Range &ents, EntityHandle seth, Tag tagh, const char *filename);
+
+    //! moab interface
+  Interface *mbImpl;
+
+#ifdef USE_MPI
+    //! ParallelComm for master, slave meshes
+  ParallelComm *pcMaster, *pcSlave;
+#endif
+  
+    //! material set numbers for fluid materials
+  std::set<int> fluidSetNos;
+
+    //! material set numbers for solid materials
+  std::set<int> solidSetNos;
+
+    //! sets defining master/slave meshes
+  EntityHandle masterSet, slaveSet;
+
+    //! sets in master/slave meshes
+  Range fluidSets[2], solidSets[2];
+  
+    //! elements in master/slave meshes
+  Range fluidElems[2], solidElems[2];
+  
+    //! filenames for master/slave meshes
+  std::string masterFileName, slaveFileName;
+
+    //! tag used for new positions
+  Tag xNew;
+  
+    //! tag name used for new positions
+  std::string xNewName;
+};
+
+  //! add a set number
+inline ErrorCode DeformMeshRemap::add_set_no(int f_or_s, int set_no) 
+{
+  std::set<int> *this_set;
+  switch (f_or_s) {
+    case FLUID:
+        this_set = &fluidSetNos; break;
+    case SOLID:
+        this_set = &solidSetNos; break;
+    default:
+        assert(false && "f_or_s should be FLUID or SOLID.");
+        return MB_FAILURE;
+  }
+
+  this_set->insert(set_no);
+  
+  return MB_SUCCESS;
+}
+  
+  //! remove a set number
+inline ErrorCode DeformMeshRemap::remove_set_no(int f_or_s, int set_no) 
+{
+  std::set<int> *this_set;
+  switch (f_or_s) {
+    case FLUID:
+        this_set = &fluidSetNos; break;
+    case SOLID:
+        this_set = &solidSetNos; break;
+    default:
+        assert(false && "f_or_s should be FLUID or SOLID.");
+        return MB_FAILURE;
+  }
+  std::set<int>::iterator sit = this_set->find(set_no);
+  if (sit != this_set->end()) {
+    this_set->erase(*sit);
+    return MB_SUCCESS;
+  }
+
+  return MB_FAILURE;
+}
+  
+  //! get the set numbers
+inline ErrorCode DeformMeshRemap::get_set_nos(int f_or_s, std::set<int> &set_nos) const
+{
+  const std::set<int> *this_set;
+  switch (f_or_s) {
+    case FLUID:
+        this_set = &fluidSetNos; break;
+    case SOLID:
+        this_set = &solidSetNos; break;
+    default:
+        assert(false && "f_or_s should be FLUID or SOLID.");
+        return MB_FAILURE;
+  }
+
+  set_nos = *this_set;
+  
+  return MB_SUCCESS;
+}
+
+ErrorCode DeformMeshRemap::execute() 
+{
+    // read master/slave files and get fluid/solid material sets
+  ErrorCode rval = read_file(MASTER, masterFileName, masterSet);
+  if (MB_SUCCESS != rval) return rval;
+  
+  rval = read_file(SLAVE, slaveFileName, slaveSet);
+  if (MB_SUCCESS != rval) return rval;
+
+  Range src_elems = solidElems[MASTER];
+  src_elems.merge(fluidElems[MASTER]);
+    // locate slave vertices in master, orig coords; do this with a data coupler, so you can
+    // later interpolate
+  Range tgt_verts, tmp_range = solidElems[SLAVE];
+  tmp_range.merge(fluidElems[SLAVE]);
+  rval = mbImpl->get_adjacencies(tmp_range, 0, false, tgt_verts, Interface::UNION);
+  RR("Failed to get target verts.");
+  
+
+    // initialize data coupler on source elements
+  DataCoupler dc_master(mbImpl, NULL, src_elems, 0);
+  
+    // locate slave vertices, caching results in dc
+  rval = dc_master.locate_points(tgt_verts); RR("Point location of tgt verts failed.");
+  int num_located = dc_master.spatial_locator()->local_num_located();
+  if (num_located != (int)tgt_verts.size()) {
+    rval = MB_FAILURE;
+    std::cout << "Only " << num_located << " out of " << tgt_verts.size() << " target points successfully located." << std::endl;
+    return rval;
+  }
+
+    // deform the master's solid mesh, put results in a new tag
+  rval = deform_master(fluidElems[MASTER], solidElems[MASTER], "xnew"); RR("");
+
+  { // to isolate the lloyd smoother & delete when done
+
+      // smooth the master mesh
+    LloydSmoother ll(mbImpl, NULL, fluidElems[MASTER], xNew);
+    rval = ll.perform_smooth();
+    RR("Failed in lloyd smoothing.");
+    cout << "Lloyd smoothing required " << ll.num_its() << " iterations." << endl;
+  }
+  
+    // map new locations to slave
+    // interpolate xNew to slave points
+  rval = dc_master.interpolate((int)DataCoupler::VOLUME, "xnew"); RR("Failed to interpolate target solution.");
+
+    // transfer xNew to coords, for master and slave
+  rval = write_to_coords(fluidElems[MASTER], xNew); RR("Failed writing tag to master fluid verts.");
+  rval = write_to_coords(tgt_verts, xNew); RR("Failed writing tag to slave verts.");
+
+  if (debug) {
+    std::string str;
+#ifdef USE_MPI
+    if (pcMaster && pcMaster->size() > 1) 
+      str = "PARALLEL=WRITE_PART";
+#endif
+    rval = mbImpl->write_file("smoothed_master.vtk", NULL, str.c_str(), &masterSet, 1);
+#ifdef USE_MPI
+    str.clear();
+    if (pcSlave && pcSlave->size() > 1) 
+      str = "PARALLEL=WRITE_PART";
+#endif
+    rval = mbImpl->write_file("slave_interp.vtk", NULL, str.c_str(), &slaveSet, 1);
+  }
+
+  return MB_SUCCESS;
+}
+
+std::string DeformMeshRemap::get_file_name(int m_or_s) const
+{
+  switch (m_or_s) {
+    case MASTER:
+        return masterFileName;
+    case SLAVE:
+        return slaveFileName;
+    default:
+        assert(false && "m_or_s should be MASTER or SLAVE.");
+        return std::string();
+  }
+}
+  
+void DeformMeshRemap::set_file_name(int m_or_s, const std::string &name) 
+{
+  switch (m_or_s) {
+    case MASTER:
+        masterFileName = name; break;
+    case SLAVE:
+        slaveFileName = name; break;
+    default:
+        assert(false && "m_or_s should be MASTER or SLAVE.");
+  }
+}
+
+DeformMeshRemap::DeformMeshRemap(Interface *impl, ParallelComm *master, ParallelComm *slave)  
+        : mbImpl(impl), pcMaster(master), pcSlave(slave), masterSet(0), slaveSet(0), xNew(0), xNewName("xnew") 
+{
+  if (!pcSlave && pcMaster)
+    pcSlave = pcMaster;
+}
+  
+DeformMeshRemap::~DeformMeshRemap() 
+{
+    // delete the tag
+  mbImpl->tag_delete(xNew);
+}
+
+int main(int argc, char **argv) {
+
+  ErrorCode rval;
+
+  ProgOptions po("Deformed mesh options");
+  po.addOpt<std::string> ("master,m", "Specify the master meshfile name" );
+  po.addOpt<std::string> ("slave,s", "Specify the slave meshfile name" );
+  po.parseCommandLine(argc, argv);
+  std::string foo;
+  string masterf, slavef;
+  if(!po.getOpt("master", &masterf))
+    masterf = string(MESH_DIR) + string("/rodquad.g");
+  if(!po.getOpt("slave", &slavef))
+    slavef = string(MESH_DIR) + string("/rodtri.g");
+
+  mb = new Core();
+
+  DeformMeshRemap *dfr;
+#ifdef USE_MPI
+  ParallelComm *pc = new ParallelComm(mb, MPI_COMM_WORLD);
+  dfr = new DeformMeshRemap(mb, pc);
+#else  
+  dfr = new DeformMeshRemap(mb);
+#endif
+  dfr->set_file_name(DeformMeshRemap::MASTER, masterf);
+  dfr->set_file_name(DeformMeshRemap::SLAVE, slavef);
+  rval = dfr->add_set_no(DeformMeshRemap::SOLID, SOLID_SETNO); RR("Failed to add solid set no.");
+  rval = dfr->add_set_no(DeformMeshRemap::FLUID, FLUID_SETNO); RR("Failed to add fluid set no.");
+  
+  rval = dfr->execute();
+  
+  delete dfr;
+  delete mb;
+  
+  return rval;
+}
+
+ErrorCode DeformMeshRemap::write_and_save(Range &ents, EntityHandle seth, Tag tagh, const char *filename) 
+{
+  ErrorCode rval = write_to_coords(ents, tagh); RR("");
+  rval = mbImpl->write_file(filename, NULL, NULL, &seth, 1); RR("");
+  return rval;
+}
+  
+ErrorCode DeformMeshRemap::write_to_coords(Range &elems, Tag tagh) 
+{
+    // write the tag to coordinates
+  Range verts;
+  ErrorCode rval = mbImpl->get_adjacencies(elems, 0, false, verts, Interface::UNION);
+  RR("Failed to get adj vertices.");
+  std::vector<double> coords(3*verts.size());
+  rval = mbImpl->tag_get_data(tagh, verts, &coords[0]);
+  RR("Failed to get tag data.");
+  rval = mbImpl->set_coords(verts, &coords[0]);
+  RR("Failed to set coordinates.");
+  return MB_SUCCESS;
+}
+
+void deform_func(const BoundBox &bbox, double *xold, double *xnew) 
+{
+/*  Deformation function based on max delx and dely at top of rod
+    const double RODWIDTH = 0.2, RODHEIGHT = 0.5;
+    // function: origin is at middle base of rod, and is .5 high
+    // top of rod is (0,.55) on left and (.2,.6) on right
+  double delx = 0.5*RODWIDTH;
+  
+  double xfrac = (xold[0] + .5*RODWIDTH)/RODWIDTH, yfrac = xold[1]/RODHEIGHT;
+  xnew[0] = xold[0] + yfrac * delx;
+  xnew[1] = xold[1] + yfrac * (1.0 + xfrac) * 0.05;
+*/
+
+/* Deformation function based on fraction of bounding box dimension in each direction */
+  double frac = 0.01; // taken from approximate relative deformation from LLNL Diablo of XX09 assys
+  CartVect *xo = reinterpret_cast<CartVect*>(xold), *xn = reinterpret_cast<CartVect*>(xnew);
+  CartVect disp = frac * (*xo - bbox.bMin);
+  *xn = *xo + disp;
+}
+  
+ErrorCode DeformMeshRemap::deform_master(Range &fluid_elems, Range &solid_elems, const char *tag_name) 
+{
+    // deform elements with an analytic function
+
+    // create the tag
+  ErrorCode rval = mbImpl->tag_get_handle((tag_name ? tag_name : ""), 3, MB_TYPE_DOUBLE, xNew, MB_TAG_CREAT|MB_TAG_DENSE);
+  RR("Failed to create xnew tag.");
+  
+    // get all the vertices and coords in the fluid, set xnew to them
+  Range verts;
+  rval = mbImpl->get_adjacencies(fluid_elems, 0, false, verts, Interface::UNION);
+  RR("Failed to get vertices.");
+  std::vector<double> coords(3*verts.size(), 0.0);
+  rval = mbImpl->get_coords(verts, &coords[0]);
+  RR("Failed to get vertex coords.");
+  rval = mbImpl->tag_set_data(xNew, verts, &coords[0]);
+  RR("Failed to set xnew tag on fluid verts.");
+
+    // get the bounding box of the solid mesh
+  BoundBox bbox;
+  bbox.update(*mbImpl, solid_elems);
+  
+    // get all the vertices and coords in the solid
+  verts.clear();
+  rval = mbImpl->get_adjacencies(solid_elems, 0, false, verts, Interface::UNION);
+  RR("Failed to get vertices.");
+  coords.resize(3*verts.size(), 0.0);
+  rval = mbImpl->get_coords(verts, &coords[0]);
+  RR("Failed to get vertex coords.");
+  unsigned int num_verts = verts.size();
+  for (unsigned int i = 0; i < num_verts; i++)
+    deform_func(bbox, &coords[3*i], &coords[3*i]);
+    
+    // set the new tag to those coords
+  rval = mbImpl->tag_set_data(xNew, verts, &coords[0]);
+  RR("Failed to set tag data.");
+  
+  return MB_SUCCESS;
+}
+
+ErrorCode DeformMeshRemap::read_file(int m_or_s, string &fname, EntityHandle &seth)
+{
+    // create meshset
+  ErrorCode rval = mbImpl->create_meshset(0, seth);
+  RR("Couldn't create master/slave set.");
+  ostringstream ostr;
+#ifdef USE_MPI
+  ParallelComm *pc = (m_or_s == MASTER ? pcMaster : pcSlave);
+  if (pc && pc->size() > 1) {
+    if (debug) ostr << "DEBUG_IO=1;CPUTIME;";
+    ostr << "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;"
+         << "PARALLEL_GHOSTS=2.0.1;PARALLEL_COMM=" << pc->get_id();
+  }
+#endif  
+  rval = mbImpl->load_file(fname.c_str(), &seth, ostr.str().c_str());
+  RR("Couldn't load master/slave mesh.");
+
+    // get material sets for solid/fluid
+  Tag tagh;
+  rval = mbImpl->tag_get_handle(MATERIAL_SET_TAG_NAME, tagh); RR("Couldn't get material set tag name.");
+  for (std::set<int>::iterator sit = solidSetNos.begin(); sit != solidSetNos.end(); sit++) {
+    Range sets;
+    int set_no = *sit;
+    const void *setno_ptr = &set_no;
+    rval = mbImpl->get_entities_by_type_and_tag(seth, MBENTITYSET, &tagh, &setno_ptr, 1, sets);
+    if (sets.empty()) rval = MB_FAILURE;
+    RR("Couldn't get any solid sets.");
+    solidSets[m_or_s].merge(sets);
+  }
+
+    // get solid entities, and dimension
+  Range tmp_range;
+  for (Range::iterator rit = solidSets[m_or_s].begin(); rit != solidSets[m_or_s].end(); rit++) {
+    rval = mbImpl->get_entities_by_handle(*rit, tmp_range, true);
+    RR("Failed to get entities in solid.");
+  }
+  int dim = mbImpl->dimension_from_handle(*tmp_range.rbegin());
+  assert(dim > 0 && dim < 4);
+  
+  solidElems[m_or_s] = tmp_range.subset_by_dimension(dim);
+
+  for (std::set<int>::iterator sit = fluidSetNos.begin(); sit != fluidSetNos.end(); sit++) {
+    Range sets;
+    int set_no = *sit;
+    const void *setno_ptr = &set_no;
+    rval = mbImpl->get_entities_by_type_and_tag(seth, MBENTITYSET, &tagh, &setno_ptr, 1, sets);
+    if (sets.empty()) rval = MB_FAILURE;
+    RR("Couldn't get any fluid sets.");
+    fluidSets[m_or_s].merge(sets);
+  }
+
+    // get fluid entities, and dimension
+  tmp_range.clear();
+  for (Range::iterator rit = fluidSets[m_or_s].begin(); rit != fluidSets[m_or_s].end(); rit++) {
+    rval = mbImpl->get_entities_by_handle(*rit, tmp_range, true);
+    RR("Failed to get entities in fluid.");
+  }
+  
+  fluidElems[m_or_s] = tmp_range.subset_by_dimension(dim);
+  
+  return MB_SUCCESS;
+}

diff --git a/examples/LloydRelaxation.cpp b/examples/LloydRelaxation.cpp
index 0cf9d1e..34002cd 100644
--- a/examples/LloydRelaxation.cpp
+++ b/examples/LloydRelaxation.cpp
@@ -14,8 +14,10 @@
  * in the current directory (H5M format must be used since the file is written in parallel).
  */
 
-#include "moab/ParallelComm.hpp"
-#include "MBParallelConventions.h"
+#ifdef USE_MPI
+#  include "moab/ParallelComm.hpp"
+#  include "MBParallelConventions.h"
+#endif
 #include "moab/Core.hpp"
 #include "moab/Skinner.hpp"
 #include "moab/CN.hpp"
@@ -30,7 +32,7 @@ string test_file_name = string(MESH_DIR) + string("/surfrandomtris-4part.h5m");
 
 #define RC if (MB_SUCCESS != rval) return rval
 
-ErrorCode perform_lloyd_relaxation(ParallelComm *pc, Range &verts, Range &cells, Tag fixed, 
+ErrorCode perform_lloyd_relaxation(Interface *mb, Range &verts, Range &cells, Tag fixed, 
                                    int num_its, int report_its);
 
 int main(int argc, char **argv)
@@ -38,7 +40,9 @@ int main(int argc, char **argv)
   int num_its = 10;
   int report_its = 1;
 
+#ifdef USE_MPI
   MPI_Init(&argc, &argv);
+#endif
 
     // need option handling here for input filename
   if (argc > 1){
@@ -49,10 +53,13 @@ int main(int argc, char **argv)
   // get MOAB and ParallelComm instances
   Interface *mb = new Core;
   if (NULL == mb) return 1;
+  int nprocs = 1;
+  
+#ifdef USE_MPI
   // get the ParallelComm instance
-  ParallelComm* pcomm = new ParallelComm(mb, MPI_COMM_WORLD);
-  int nprocs = pcomm->size();
-
+  ParallelComm *pcomm = new ParallelComm(mb, MPI_COMM_WORLD);
+  nprocs = pcomm->size();
+#endif
   string options;
   if (nprocs > 1) // if reading in parallel, need to tell it how
     options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PARALLEL_GHOSTS=2.0.1;DEBUG_IO=0;DEBUG_PIO=0";
@@ -76,34 +83,45 @@ int main(int argc, char **argv)
     // ok to mark non-owned skin vertices too, I won't move those anyway
     // use MOAB's skinner class to find the skin
   Skinner skinner(mb);
-  rval = skinner.find_skin(faces, true, skin_verts); RC; // 'true' param indicates we want vertices back, not faces
+  rval = skinner.find_skin(0, faces, true, skin_verts); RC; // 'true' param indicates we want vertices back, not faces
 
   std::vector<int> fix_tag(skin_verts.size(), 1); // initialized to 1 to indicate fixed
   rval = mb->tag_set_data(fixed, skin_verts, &fix_tag[0]); RC;
 
     // now perform the Lloyd relaxation
-  rval = perform_lloyd_relaxation(pcomm, verts, faces, fixed, num_its, report_its); RC;
+  rval = perform_lloyd_relaxation(mb, verts, faces, fixed, num_its, report_its); RC;
 
     // delete fixed tag, since we created it here
   rval = mb->tag_delete(fixed); RC;
   
     // output file, using parallel write
-  rval = mb->write_file("lloydfinal.h5m", NULL, "PARALLEL=WRITE_PART"); RC;
+
+#ifdef USE_MPI
+  options = "PARALLEL=WRITE_PART";
+#endif
+
+  rval = mb->write_file("lloydfinal.h5m", NULL, options.c_str()); RC;
 
     // delete MOAB instance
   delete mb;
   
+#ifdef USE_MPI
   MPI_Finalize();
+#endif
 
   return 0;
 }
 
-ErrorCode perform_lloyd_relaxation(ParallelComm *pcomm, Range &verts, Range &faces, Tag fixed, 
+ErrorCode perform_lloyd_relaxation(Interface *mb, Range &verts, Range &faces, Tag fixed, 
                                    int num_its, int report_its) 
 {
   ErrorCode rval;
-  Interface *mb = pcomm->get_moab();
-  int nprocs = pcomm->size();
+  int nprocs = 1;
+
+#ifdef USE_MPI
+  ParallelComm *pcomm = ParallelComm::get_pcomm(mb, 0);
+  nprocs = pcomm->size();
+#endif
   
     // perform Lloyd relaxation:
     // 1. setup: set vertex centroids from vertex coords; filter to owned verts; get fixed tags
@@ -120,8 +138,10 @@ ErrorCode perform_lloyd_relaxation(ParallelComm *pcomm, Range &verts, Range &fac
     // filter verts down to owned ones and get fixed tag for them
   Range owned_verts, shared_owned_verts;
   if (nprocs > 1) {
+#ifdef USE_MPI
     rval = pcomm->filter_pstatus(verts, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_verts);
     if (rval != MB_SUCCESS) return rval;
+#endif
   }
   else
     owned_verts = verts;
@@ -133,11 +153,13 @@ ErrorCode perform_lloyd_relaxation(ParallelComm *pcomm, Range &verts, Range &fac
   vcentroids.resize(3*owned_verts.size());
   rval = mb->tag_get_data(centroid, owned_verts, &vcentroids[0]); RC;
 
+#ifdef USE_MPI
     // get shared owned verts, for exchanging tags
   rval = pcomm->get_shared_entities(-1, shared_owned_verts, 0, false, true); RC;
     // workaround: if no shared owned verts, put a non-shared one in the list, to prevent exchanging tags
     // for all shared entities
   if (shared_owned_verts.empty()) shared_owned_verts.insert(*verts.begin());
+#endif
   
     // some declarations for later iterations
   std::vector<double> fcentroids(3*faces.size()); // fcentroids for face centroids
@@ -195,16 +217,22 @@ ErrorCode perform_lloyd_relaxation(ParallelComm *pcomm, Range &verts, Range &fac
 
     // 2c. exchange tags on owned verts
     if (nprocs > 1) {
+#ifdef USE_MPI
       rval = pcomm->exchange_tags(centroid, shared_owned_verts); RC;
+#endif
     }
 
 
     if (!(nit%report_its)) {
         // global reduce for maximum delta, then report it
       double global_max = mxdelta;
+      int myrank = 0;
+#ifdef USE_MPI
       if (nprocs > 1)
         MPI_Reduce(&mxdelta, &global_max, 1, MPI_DOUBLE, MPI_MAX, 0, pcomm->comm());
-      if (1 == nprocs || !pcomm->rank()) 
+      myrank = pcomm->rank();
+#endif
+      if (1 == nprocs || !myrank) 
         cout << "Max delta = " << global_max << endl;
     }
   }

diff --git a/examples/makefile b/examples/makefile
index 5ae5af0..a6e3d1f 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -4,7 +4,7 @@ include ${MOAB_DIR}/lib/iMesh-Defs.inc
 
 .SUFFIXES: .o .cpp .F90
 
-# MESH_DIR is the top-level MOAB source directory, used to locate mesh files that come with MOAB source
+# MESH_DIR is the directory containing mesh files that come with MOAB source
 MESH_DIR="../MeshFiles/unittest"
 
 EXAMPLES = HelloMOAB GetEntities SetsNTags StructuredMeshSimple DirectAccessWithHoles DirectAccessNoHoles 
@@ -14,45 +14,48 @@ EXOIIEXAMPLES = TestExodusII
 
 default: ${EXAMPLES}
 
-HelloMOAB : HelloMOAB.o
+HelloMOAB : HelloMOAB.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-GetEntities: GetEntities.o
+GetEntities: GetEntities.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-SetsNTags: SetsNTags.o
+SetsNTags: SetsNTags.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-LloydRelaxation: LloydRelaxation.o
+LloydRelaxation: LloydRelaxation.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-StructuredMeshSimple : StructuredMeshSimple.o
+StructuredMeshSimple : StructuredMeshSimple.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
 
-DirectAccessWithHoles: DirectAccessWithHoles.o
+DirectAccessWithHoles: DirectAccessWithHoles.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-DirectAccessNoHoles: DirectAccessNoHoles.o
+DirectAccessNoHoles: DirectAccessNoHoles.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-DirectAccessNoHolesF90: DirectAccessNoHolesF90.o
+DirectAccessNoHolesF90: DirectAccessNoHolesF90.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${IMESH_LIBS}
 
-ReduceExchangeTags : ReduceExchangeTags.o
+ReduceExchangeTags : ReduceExchangeTags.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-HelloParMOAB: HelloParMOAB.o
+HelloParMOAB: HelloParMOAB.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} 
 
-TestExodusII: TestExodusII.o
+TestExodusII: TestExodusII.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
-point_in_elem_search: point_in_elem_search.o
+point_in_elem_search: point_in_elem_search.o ${MOAB_LIBDIR}/libMOAB.la
 	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK}
 
 PushParMeshIntoMoabF90: PushParMeshIntoMoabF90.o
 	${MOAB_CXX} -o $@ $< ${IMESH_LIBS} -lgfortran -L/usr/lib/openmpi/lib -lmpi_f90 -lmpi_f77 -lmpi -lopen-rte -lopen-pal -ldl 
 
+DeformMeshRemap: DeformMeshRemap.o ${MOAB_LIBDIR}/libMOAB.la
+	${MOAB_CXX} -o $@ $< ${MOAB_LIBS_LINK} -lmbcoupler ${MOAB_LIBS_LINK} 
+
 clean:
 	rm -rf *.o ${EXAMPLES} ${PAREXAMPLES} ${EXOIIEXAMPLES}
 

diff --git a/src/AdaptiveKDTree.cpp b/src/AdaptiveKDTree.cpp
index f66acbc..1324c30 100644
--- a/src/AdaptiveKDTree.cpp
+++ b/src/AdaptiveKDTree.cpp
@@ -1303,7 +1303,8 @@ namespace moab {
 
     ErrorCode AdaptiveKDTree::point_search(const double *point,
                                            EntityHandle& leaf_out,
-                                           double tol,
+                                           const double iter_tol,
+                                           const double inside_tol,
                                            bool *multiple_leaves,
                                            EntityHandle *start_node,
                                            CartVect *params)
@@ -1322,7 +1323,7 @@ namespace moab {
       treeStats.nodesVisited++;
       ErrorCode rval = get_bounding_box(box, &node);
       if (MB_SUCCESS != rval) return rval;
-      if (!box.contains_point(point, tol)) return MB_SUCCESS;
+      if (!box.contains_point(point, iter_tol)) return MB_SUCCESS;
       
       rval = moab()->get_child_meshsets( node, children );
       if (MB_SUCCESS != rval)
@@ -1346,7 +1347,7 @@ namespace moab {
 
       treeStats.leavesVisited++;
       if (myEval && params) {
-        rval = myEval->find_containing_entity(node, point, tol,
+        rval = myEval->find_containing_entity(node, point, iter_tol, inside_tol,
                                               leaf_out, params->array(), &treeStats.leafObjectTests);
         if (MB_SUCCESS != rval) return rval;
       }
@@ -1358,7 +1359,8 @@ namespace moab {
 
     ErrorCode AdaptiveKDTree::point_search(const double *point,
                                            AdaptiveKDTreeIter& leaf_it,
-                                           double tol,
+                                           const double iter_tol,
+                                           const double /*inside_tol*/,
                                            bool *multiple_leaves,
                                            EntityHandle *start_node)
     {
@@ -1372,7 +1374,7 @@ namespace moab {
       leaf_it.mBox[1] = boundBox.bMax;
 
         // test that point is inside tree
-      if (!boundBox.contains_point(point, tol)) {
+      if (!boundBox.contains_point(point, iter_tol)) {
         treeStats.nodesVisited++;
         return MB_ENTITY_NOT_FOUND;
       }
@@ -1423,7 +1425,8 @@ namespace moab {
     ErrorCode AdaptiveKDTree::distance_search(const double from_point[3],
                                               const double distance,
                                               std::vector<EntityHandle>& result_list,
-                                              double tol,
+                                              const double iter_tol,
+                                              const double inside_tol,
                                               std::vector<double> *result_dists,
                                               std::vector<CartVect> *result_params,
                                               EntityHandle *tree_root)
@@ -1445,7 +1448,7 @@ namespace moab {
         // (zero if inside box)
       BoundBox box;
       rval = get_bounding_box(box);
-      if (MB_SUCCESS == rval && !box.contains_point(from_point, tol)) {
+      if (MB_SUCCESS == rval && !box.contains_point(from_point, iter_tol)) {
         treeStats.nodesVisited++;
         return MB_SUCCESS;
       }
@@ -1484,7 +1487,7 @@ namespace moab {
           if (myEval && result_params) {
             EntityHandle ent;
             CartVect params;
-            rval = myEval->find_containing_entity(node.handle, from_point, tol,
+            rval = myEval->find_containing_entity(node.handle, from_point, iter_tol, inside_tol,
                                                   ent, params.array(), &treeStats.leafObjectTests);
             if (MB_SUCCESS != rval) return rval;
             else if (ent) {
@@ -1802,7 +1805,7 @@ namespace moab {
         // the same distance from the input point as the current closest
         // point is.
       CartVect diff = closest_pt - from;
-      rval = distance_search(from_coords, sqrt(diff%diff), leaves, 0.0, NULL, NULL, &tree_root);
+      rval = distance_search(from_coords, sqrt(diff%diff), leaves, 1.0e-10, 1.0e-6, NULL, NULL, &tree_root);
       if (MB_SUCCESS != rval) return rval;
 
         // Check any close leaves to see if they contain triangles that
@@ -1834,7 +1837,7 @@ namespace moab {
 
         // get leaves of tree that intersect sphere
       assert(tree_root);
-      rval = distance_search(center, radius, leaves, 0.0, NULL, NULL, &tree_root);
+      rval = distance_search(center, radius, leaves, 1.0e-10, 1.0e-6, NULL, NULL, &tree_root);
       if (MB_SUCCESS != rval) return rval;
   
         // search each leaf for triangles intersecting sphere

diff --git a/src/BVHTree.cpp b/src/BVHTree.cpp
index 8903070..b65eae4 100644
--- a/src/BVHTree.cpp
+++ b/src/BVHTree.cpp
@@ -435,7 +435,8 @@ namespace moab
 
     ErrorCode BVHTree::find_point(const std::vector<double> &point, 
                                   const unsigned int &index,
-                                  const double tol,
+                                  const double iter_tol,
+                                  const double inside_tol,
                                   std::pair<EntityHandle, CartVect> &result)
     {
       if (index == 0) treeStats.numTraversals++;
@@ -453,7 +454,7 @@ namespace moab
         for(Range::iterator i = entities.begin(); i != entities.end(); i++) {
           treeStats.leafObjectTests++;
           myEval->set_ent_handle(*i);
-          myEval->reverse_eval(&point[0], tol, params.array(), &is_inside);
+          myEval->reverse_eval(&point[0], iter_tol, inside_tol, params.array(), &is_inside);
           if (is_inside) {
             result.first = *i;
             result.second = params;
@@ -469,11 +470,11 @@ namespace moab
       rval = mbImpl->get_child_meshsets(startSetHandle+index, children);
       if (MB_SUCCESS != rval || children.size() != 2) return rval;
       
-      if((node.Lmax+tol) < (node.Rmin-tol)){
-        if(point[node.dim] <= (node.Lmax + tol))
-          return find_point(point, children[0]-startSetHandle, tol, result);
-        else if(point[ node.dim] >= (node.Rmin - tol))
-          return find_point(point, children[1]-startSetHandle, tol, result);
+      if((node.Lmax+iter_tol) < (node.Rmin-iter_tol)){
+        if(point[node.dim] <= (node.Lmax + iter_tol))
+          return find_point(point, children[0]-startSetHandle, iter_tol, inside_tol, result);
+        else if(point[ node.dim] >= (node.Rmin - iter_tol))
+          return find_point(point, children[1]-startSetHandle, iter_tol, inside_tol, result);
         result = std::make_pair(0, CartVect(&point[0])); //point lies in empty space.
         return MB_SUCCESS;
       }
@@ -482,11 +483,11 @@ namespace moab
         //left of Rmin, you must be on the left
         //we can't be sure about the boundaries since the boxes overlap
         //this was a typo in the paper which caused pain.
-      if(point[node.dim] < (node.Rmin - tol))
-        return find_point(point, children[0]-startSetHandle, tol, result);
+      if(point[node.dim] < (node.Rmin - iter_tol))
+        return find_point(point, children[0]-startSetHandle, iter_tol, inside_tol, result);
         //if you are on the right Lmax, you must be on the right
-      else if(point[ node.dim] > (node.Lmax+tol))
-        return find_point(point, children[1]-startSetHandle, tol, result);
+      else if(point[ node.dim] > (node.Lmax+iter_tol))
+        return find_point(point, children[1]-startSetHandle, iter_tol, inside_tol, result);
 
         /* pg5 of paper
          * However, instead of always traversing either subtree
@@ -501,22 +502,22 @@ namespace moab
         //branch predicted..
         //bool dir = (point[ node.dim] - node.Rmin) <= 
         //				(node.Lmax - point[ node.dim]);
-      find_point(point, children[0]-startSetHandle, tol, result);
+      find_point(point, children[0]-startSetHandle, iter_tol, inside_tol, result);
       if(result.first == 0){ 
-        return find_point(point, children[1]-startSetHandle, tol, result);
+        return find_point(point, children[1]-startSetHandle, iter_tol, inside_tol, result);
       }
       return MB_SUCCESS;
     }
 
-    EntityHandle BVHTree::bruteforce_find(const double *point, const double tol) {
+    EntityHandle BVHTree::bruteforce_find(const double *point, const double iter_tol, const double inside_tol) {
       treeStats.numTraversals++;
       CartVect params;
       for(unsigned int i = 0; i < myTree.size(); i++) {
-        if(myTree[i].dim != 3 || !myTree[i].box.contains_point(point, tol)) continue;
+        if(myTree[i].dim != 3 || !myTree[i].box.contains_point(point, iter_tol)) continue;
         if (myEval) {
           EntityHandle entity = 0;
           treeStats.leavesVisited++;
-          ErrorCode rval = myEval->find_containing_entity(startSetHandle+i, point, tol,
+          ErrorCode rval = myEval->find_containing_entity(startSetHandle+i, point, iter_tol, inside_tol,
                                                           entity, params.array(), &treeStats.leafObjectTests);
           if (entity) return entity;
           else if (MB_SUCCESS != rval) return 0;
@@ -542,7 +543,8 @@ namespace moab
 
     ErrorCode BVHTree::point_search(const double *point,
                                     EntityHandle& leaf_out,
-                                    double tol,
+                                    const double iter_tol,
+                                    const double inside_tol,
                                     bool *multiple_leaves,
                                     EntityHandle *start_node,
                                     CartVect *params) 
@@ -572,7 +574,7 @@ namespace moab
           // test box of this node
         ErrorCode rval = get_bounding_box(box, &this_set);
         if (MB_SUCCESS != rval) return rval;
-        if (!box.contains_point(point, tol)) continue;
+        if (!box.contains_point(point, iter_tol)) continue;
 
           // else if not a leaf, test children & put on list
         else if (myTree[ind].dim != 3) {
@@ -581,7 +583,7 @@ namespace moab
           continue;
         }
         else if (myTree[ind].dim == 3 && myEval && params) {
-          rval = myEval->find_containing_entity(startSetHandle+ind, point, tol,
+          rval = myEval->find_containing_entity(startSetHandle+ind, point, iter_tol, inside_tol,
                                                 leaf_out, params->array(), &treeStats.leafObjectTests);
           if (leaf_out || MB_SUCCESS != rval) return rval;
         }
@@ -599,7 +601,8 @@ namespace moab
     ErrorCode BVHTree::distance_search(const double from_point[3],
                                        const double distance,
                                        std::vector<EntityHandle>& result_list,
-                                       double params_tol,
+                                       const double iter_tol,
+                                       const double inside_tol,
                                        std::vector<double> *result_dists,
                                        std::vector<CartVect> *result_params,
                                        EntityHandle *tree_root)
@@ -653,7 +656,7 @@ namespace moab
         if (myEval && result_params) {
           EntityHandle ent;
           CartVect params;
-          rval = myEval->find_containing_entity(startSetHandle+ind, from_point, params_tol,
+          rval = myEval->find_containing_entity(startSetHandle+ind, from_point, iter_tol, inside_tol,
                                                 ent, params.array(), &treeStats.leafObjectTests);
           if (MB_SUCCESS != rval) return rval;
           else if (ent) {

diff --git a/src/LloydSmoother.cpp b/src/LloydSmoother.cpp
new file mode 100644
index 0000000..b1614d2
--- /dev/null
+++ b/src/LloydSmoother.cpp
@@ -0,0 +1,232 @@
+#include "moab/LloydSmoother.hpp"
+#include "moab/Error.hpp"
+#include "moab/Skinner.hpp"
+#include "moab/CN.hpp"
+#include "moab/CartVect.hpp"
+#include "moab/BoundBox.hpp"
+
+#ifdef USE_MPI
+#include "moab/ParallelComm.hpp"
+#include "MBParallelConventions.h"
+#endif
+
+#include <iostream>
+
+#define RR(a) if (MB_SUCCESS != rval) {        \
+    errorHandler->set_last_error(a);                \
+    return rval;}
+
+namespace moab {
+  
+LloydSmoother::LloydSmoother(Interface *impl, ParallelComm *pc, Range &elms, Tag ctag,
+                             Tag ftag, double at, double rt) 
+        : mbImpl(impl), myPcomm(pc), myElems(elms), coordsTag(ctag), fixedTag(ftag), absTol(at), relTol(rt),
+          reportIts(0), numIts(0), iCreatedTag(false)
+{
+  ErrorCode rval = mbImpl->query_interface(errorHandler);
+  if (rval) throw rval;
+}
+
+LloydSmoother::~LloydSmoother() 
+{
+  if (iCreatedTag && fixedTag) {
+    ErrorCode rval = mbImpl->tag_delete(fixedTag);
+    if (rval) throw rval;
+  }
+}
+    
+ErrorCode LloydSmoother::perform_smooth() 
+{
+  ErrorCode rval;
+
+    // first figure out tolerance to use
+  if (0 > absTol) {
+      // no tolerance set - get one relative to bounding box around elements
+    BoundBox bb;
+    rval = bb.update(*mbImpl, myElems);
+    RR("Failed to compute bounding box around elements.");
+    absTol = relTol * bb.diagonal_length();
+  }
+
+    // initialize if we need to
+  rval = initialize();
+  RR("Failed to initialize.");
+
+    // get all vertices
+  Range verts;
+  rval = mbImpl->get_adjacencies(myElems, 0, false, verts, Interface::UNION);
+  RR("Failed to get all vertices.");
+  
+    // perform Lloyd relaxation:
+    // 1. setup: set vertex centroids from vertex coords; filter to owned verts; get fixed tags
+
+    // get all verts coords into tag; don't need to worry about filtering out fixed verts, 
+    // we'll just be setting to their fixed coords
+  std::vector<double> vcentroids(3*verts.size());
+  if (!coordsTag) {
+    rval = mbImpl->get_coords(verts, &vcentroids[0]); RR("Failed to get vert coords.");
+  }
+  else {
+    rval = mbImpl->tag_get_data(coordsTag, verts, &vcentroids[0]); RR("Failed to get vert coords tag values.");
+  }
+
+  Tag centroid;
+  rval = mbImpl->tag_get_handle("", 3, MB_TYPE_DOUBLE, centroid, MB_TAG_CREAT | MB_TAG_DENSE); 
+  RR("Couldn't get tag handle.");
+  rval = mbImpl->tag_set_data(centroid, verts, &vcentroids[0]); RR("Failed setting centroid tag.");
+
+  Range owned_verts, shared_owned_verts;
+#ifdef USE_MPI
+    // filter verts down to owned ones and get fixed tag for them
+  if (myPcomm && myPcomm->size() > 1) {
+    rval = myPcomm->filter_pstatus(verts, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &owned_verts);
+    RR("Failed to filter on pstatus.");
+      // get shared owned verts, for exchanging tags
+    rval = myPcomm->filter_pstatus(owned_verts, PSTATUS_SHARED, PSTATUS_AND, -1, &shared_owned_verts);
+    RR("Failed to filter for shared owned.");
+      // workaround: if no shared owned verts, put a non-shared one in the list, to prevent exchanging tags
+      // for all shared entities
+    if (shared_owned_verts.empty()) shared_owned_verts.insert(*verts.begin());
+  }
+  else
+    owned_verts = verts;
+#else
+  owned_verts = verts;
+#endif
+  
+  std::vector<unsigned char> fix_tag(owned_verts.size());
+  rval = mbImpl->tag_get_data(fixedTag, owned_verts, &fix_tag[0]); RR("Failed to get fixed tag.");
+
+    // now fill vcentroids array with positions of just owned vertices, since those are the ones
+    // we're actually computing
+  vcentroids.resize(3*owned_verts.size());
+  rval = mbImpl->tag_get_data(centroid, owned_verts, &vcentroids[0]); RR("Failed to get centroid tag.");
+
+    // some declarations for later iterations
+  std::vector<double> fcentroids(3*myElems.size()); // fcentroids for element centroids
+  std::vector<double> ctag(3*CN::MAX_NODES_PER_ELEMENT);  // temporary coordinate storage for verts bounding an element
+  const EntityHandle *conn;  // const ptr & size to elem connectivity
+  int nconn;
+  Range::iterator eit, vit;  // for iterating over elems, verts
+  int e, v;  // for indexing into centroid vectors
+  std::vector<EntityHandle> adj_elems;  // used in vertex iteration
+  
+    // 2. while !converged
+  double resid = DBL_MAX;
+  numIts = 0;
+  while (resid > absTol) {
+    numIts++;
+    resid = 0.0;
+    
+    // 2a. foreach elem: centroid = sum(vertex centroids)/num_verts_in_cell
+    for (eit = myElems.begin(), e = 0; eit != myElems.end(); eit++, e++) {
+        // get verts for this elem
+      rval = mbImpl->get_connectivity(*eit, conn, nconn); RR("Failed to get connectivity.");
+        // get centroid tags for those verts
+      rval = mbImpl->tag_get_data(centroid, conn, nconn, &ctag[0]); RR("Failed to get centroid.");
+      fcentroids[3*e+0] = fcentroids[3*e+1] = fcentroids[3*e+2] = 0.0;
+      for (v = 0; v < nconn; v++) {
+        fcentroids[3*e+0] += ctag[3*v+0];
+        fcentroids[3*e+1] += ctag[3*v+1];
+        fcentroids[3*e+2] += ctag[3*v+2];
+      }
+      for (v = 0; v < 3; v++) fcentroids[3*e+v] /= nconn;
+    }
+    rval = mbImpl->tag_set_data(centroid, myElems, &fcentroids[0]); RR("Failed to set elem centroid.");
+
+      // 2b. foreach owned vertex: 
+    for (vit = owned_verts.begin(), v = 0; vit != owned_verts.end(); vit++, v++) {
+        // if !fixed
+      if (fix_tag[v]) continue;
+        // vertex centroid = sum(cell centroids)/ncells
+      adj_elems.clear();
+      rval = mbImpl->get_adjacencies(&(*vit), 1, 2, false, adj_elems); RR("Failed getting adjs.");
+      rval = mbImpl->tag_get_data(centroid, &adj_elems[0], adj_elems.size(), &fcentroids[0]); 
+      RR("Failed to get elem centroid.");
+      double vnew[] = {0.0, 0.0, 0.0};
+      for (e = 0; e < (int)adj_elems.size(); e++) {
+        vnew[0] += fcentroids[3*e+0];
+        vnew[1] += fcentroids[3*e+1];
+        vnew[2] += fcentroids[3*e+2];
+      }
+      for (e = 0; e < 3; e++) vnew[e] /= adj_elems.size();
+      double delta = (CartVect(vnew)-CartVect(&vcentroids[3*v])).length();
+      resid = (v ? std::max(resid, delta) : delta);
+      for (e = 0; e < 3; e++) vcentroids[3*v+e] = vnew[e];
+    }
+
+      // set the centroid tag; having them only in vcentroids array isn't enough, as vertex centroids are
+      // accessed randomly in loop over faces
+    rval = mbImpl->tag_set_data(centroid, owned_verts, &vcentroids[0]); RR("Failed to set vertex centroid.");
+
+#ifdef USE_MPI
+    // 2c. exchange tags on owned verts
+    if (myPcomm && myPcomm->size() > 1) {
+      rval = myPcomm->exchange_tags(centroid, shared_owned_verts); RR("Failed to exchange tags.");
+    }
+#endif
+
+    if (reportIts && !(numIts%reportIts)) {
+      double global_max = resid;
+#ifdef USE_MPI
+        // global reduce for maximum delta, then report it
+      if (myPcomm && myPcomm->size() > 1)
+        MPI_Reduce(&resid, &global_max, 1, MPI_DOUBLE, MPI_MAX, 0, myPcomm->comm());
+      if (!myPcomm || !myPcomm->rank()) 
+#endif
+        std::cout << "Max residual = " << global_max << std::endl;
+    }
+
+  } // end while
+  
+    // write the tag back onto vertex coordinates
+  if (!coordsTag) {
+    rval = mbImpl->set_coords(owned_verts, &vcentroids[0]); RR("Failed to set vertex coords.");
+  }
+  else {
+    rval = mbImpl->tag_set_data(coordsTag, owned_verts, &vcentroids[0]); 
+    RR("Failed to set vert coords tag values.");
+  }
+
+  return MB_SUCCESS;
+}
+
+ErrorCode LloydSmoother::initialize()
+{
+  ErrorCode rval = MB_SUCCESS;
+  
+    // first, check for tag; if we don't have it, make one and mark skin as fixed
+  if (!fixedTag) {
+    unsigned char fixed = 0x0;
+    rval = mbImpl->tag_get_handle("", 1, MB_TYPE_OPAQUE, fixedTag, MB_TAG_DENSE|MB_TAG_CREAT, &fixed);
+    RR("Trouble making fixed tag.");
+    iCreatedTag = true;
+  
+      // get the skin; get facets, because we might need to filter on shared entities
+    Skinner skinner(mbImpl);
+    Range skin, skin_verts;
+    rval = skinner.find_skin(0, myElems, false, skin);
+    RR("Unable to find skin.");
+
+#ifdef USE_MPI
+      // need to do a little extra if we're working in parallel
+    if (myPcomm) {
+        // filter out ghost and interface facets
+      rval = myPcomm->filter_pstatus(skin, PSTATUS_GHOST|PSTATUS_INTERFACE, PSTATUS_NOT);
+      RR("Failed to filter on shared status.");
+    }
+#endif
+      // get the vertices from those entities
+    rval = mbImpl->get_adjacencies(skin, 0, false, skin_verts, Interface::UNION);
+    RR("Trouble getting vertices.");
+    
+      // mark them fixed
+    std::vector<unsigned char> marks(skin.size(), 0x1);
+    rval = mbImpl->tag_set_data(fixedTag, skin_verts, &marks[0]);
+    RR("Unable to set tag on skin.");
+  }
+  
+  return MB_SUCCESS;
+}
+
+}

diff --git a/src/LocalDiscretization/ElemEvaluator.cpp b/src/LocalDiscretization/ElemEvaluator.cpp
index b132da9..4ca3943 100644
--- a/src/LocalDiscretization/ElemEvaluator.cpp
+++ b/src/LocalDiscretization/ElemEvaluator.cpp
@@ -6,6 +6,7 @@
 
 // need to include eval set types here to support get_eval_set; alternative would be to have some
 // type of registration, but we'd still need static registration for the built-in types
+#include "moab/LinearTri.hpp"
 #include "moab/LinearQuad.hpp"
 #include "moab/LinearTet.hpp"
 #include "moab/LinearHex.hpp"
@@ -16,12 +17,12 @@
 namespace moab { 
     ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
                                         const double *posn, const double *verts, const int nverts, 
-                                        const int ndim, const double tol, double *work, 
-                                        double *params, bool *inside) {
+                                        const int ndim, const double iter_tol, const double inside_tol, 
+                                        double *work, double *params, bool *inside) {
         // TODO: should differentiate between epsilons used for
         // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
         // right now, fix the tolerance used for NR
-      const double error_tol_sqr = tol*tol;
+      const double error_tol_sqr = iter_tol*iter_tol;
       CartVect *cvparams = reinterpret_cast<CartVect*>(params);
       const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
 
@@ -30,41 +31,48 @@ namespace moab {
   
       CartVect new_pos;
         // evaluate that first guess to get a new position
-      ErrorCode rval = (*eval)(cvparams->array(), verts, ndim, ndim, work, new_pos.array());
+      ErrorCode rval = (*eval)(cvparams->array(), verts, ndim, 
+                               3, // hardwire to num_tuples to 3 since the field is coords
+                               work, new_pos.array());
       if (MB_SUCCESS != rval) return rval;
       
         // residual is diff between old and new pos; need to minimize that
       CartVect res = new_pos - *cvposn;
       Matrix3 J;
+      bool dum, *tmp_inside = (inside ? inside : &dum);
 
       int iters=0;
         // while |res| larger than tol
       while (res % res > error_tol_sqr) {
         if(++iters>10) {
-          if (inside) {
-              // if we haven't converged but we're outside, that's defined as success
-            *inside = (*inside_f)(params, ndim, tol);
-            if (!(*inside)) return MB_SUCCESS;
-          }
-          return MB_FAILURE;
+            // if we haven't converged but we're outside, that's defined as success
+          *tmp_inside = (*inside_f)(params, ndim, inside_tol);
+          if (!(*tmp_inside)) return MB_SUCCESS;
+          else return MB_FAILURE;
         }
 
           // get jacobian at current params
         rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);
         double det = J.determinant();
-        assert(det > std::numeric_limits<double>::epsilon());
+        if (det < std::numeric_limits<double>::epsilon()) {
+          *tmp_inside = (*inside_f)(params, ndim, inside_tol);
+          if (!(*tmp_inside)) return MB_SUCCESS;
+          else return MB_FAILURE;
+        }
 
           // new params tries to eliminate residual
         *cvparams -= J.inverse(1.0/det) * res;
 
           // get the new forward-evaluated position, and its difference from the target pt
-        rval = (*eval)(params, verts, ndim, ndim, work, new_pos.array());
+        rval = (*eval)(params, verts, ndim, 
+                       3, // hardwire to num_tuples to 3 since the field is coords
+                       work, new_pos.array());
         if (MB_SUCCESS != rval) return rval;
         res = new_pos - *cvposn;
       }
 
       if (inside)
-        *inside = (*inside_f)(params, ndim, tol);
+        *inside = (*inside_f)(params, ndim, inside_tol);
 
       return MB_SUCCESS;
     }// Map::evaluate_reverse()
@@ -85,6 +93,7 @@ namespace moab {
         case MBEDGE:
             break;
         case MBTRI:
+            if (LinearTri::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
             break;
         case MBQUAD:
             if (LinearQuad::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
@@ -105,9 +114,9 @@ namespace moab {
       return MB_NOT_IMPLEMENTED;
     }
       
-    ErrorCode ElemEvaluator::find_containing_entity(Range &entities, const double *point, double tol, 
-                                                    EntityHandle &containing_ent, double *params, 
-                                                    unsigned int *num_evals) 
+    ErrorCode ElemEvaluator::find_containing_entity(Range &entities, const double *point, const double iter_tol, 
+                                                    const double inside_tol, EntityHandle &containing_ent, 
+                                                    double *params, unsigned int *num_evals) 
     {
       bool is_inside;
       ErrorCode rval = MB_SUCCESS;
@@ -116,7 +125,7 @@ namespace moab {
       for(i = entities.begin(); i != entities.end(); i++) {
         nevals++;
         set_ent_handle(*i);
-        rval = reverse_eval(point, tol, params, &is_inside);
+        rval = reverse_eval(point, iter_tol, inside_tol, params, &is_inside);
         if (MB_SUCCESS != rval) return rval;
         if (is_inside) break;
       }

diff --git a/src/LocalDiscretization/LinearHex.cpp b/src/LocalDiscretization/LinearHex.cpp
index 14de2d9..5e730af 100644
--- a/src/LocalDiscretization/LinearHex.cpp
+++ b/src/LocalDiscretization/LinearHex.cpp
@@ -96,10 +96,12 @@ namespace moab
 
     ErrorCode LinearHex::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                         const double *posn, const double *verts, const int nverts, const int ndim,
-                                        const double tol, double *work, double *params, bool *is_inside)
+                                        const double iter_tol, const double inside_tol, double *work, 
+                                        double *params, bool *is_inside)
     {
       assert(posn && verts);
-      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, iter_tol, inside_tol, work, 
+                                       params, is_inside);
     }
 
     bool LinearHex::insideFcn(const double *params, const int ndim, const double tol)

diff --git a/src/LocalDiscretization/LinearQuad.cpp b/src/LocalDiscretization/LinearQuad.cpp
index ddd4918..63c9959 100644
--- a/src/LocalDiscretization/LinearQuad.cpp
+++ b/src/LocalDiscretization/LinearQuad.cpp
@@ -16,23 +16,23 @@ namespace moab
       */
     const double LinearQuad::gauss[1][2] = { {  2.0,           0.0          } };
 
-    ErrorCode LinearQuad::jacobianFcn(const double *params, const double *verts, const int /*nverts*/, const int ndim, 
+    ErrorCode LinearQuad::jacobianFcn(const double *params, const double *verts, const int /*nverts*/, const int /*ndim*/, 
                                       double *, double *result) 
     {
       Matrix3 *J = reinterpret_cast<Matrix3*>(result);
       *J = Matrix3(0.0);
       for (unsigned i = 0; i < 4; ++i) {
-        const double   params_p = 1 + params[0]*corner[i][0];
+        const double   xi_p = 1 + params[0]*corner[i][0];
         const double  eta_p = 1 + params[1]*corner[i][1];
-        const double dNi_dparams   = corner[i][0] * eta_p;
-        const double dNi_deta  = corner[i][1] *  params_p;
-        (*J)(0,0) += dNi_dparams   * verts[i*ndim+0];
-        (*J)(1,0) += dNi_dparams   * verts[i*ndim+1];
-        (*J)(0,1) += dNi_deta  * verts[i*ndim+0];
-        (*J)(1,1) += dNi_deta  * verts[i*ndim+1];
+        const double dNi_dxi   = corner[i][0] * eta_p;
+        const double dNi_deta  = corner[i][1] * xi_p;
+        (*J)(0,0) += dNi_dxi   * verts[i*3+0];
+        (*J)(1,0) += dNi_dxi   * verts[i*3+1];
+        (*J)(0,1) += dNi_deta  * verts[i*3+0];
+        (*J)(1,1) += dNi_deta  * verts[i*3+1];
       }
-      (*J)(2,2) = 1.0; /* to make sure the Jacobian determinant is non-zero */
       (*J) *= 0.25;
+      (*J)(2,2) = 1.0; /* to make sure the Jacobian determinant is non-zero */
       return MB_SUCCESS;
     }// LinearQuad::jacobian()
 
@@ -62,7 +62,7 @@ namespace moab
         for(unsigned int j2 = 0; j2 < LinearQuad::gauss_count; ++j2) {
           x[1] = LinearQuad::gauss[j2][1];
           double w2 = LinearQuad::gauss[j2][0];
-          rval = evalFcn(x.array(),field, ndim, num_tuples, NULL, tmp_result);
+          rval = evalFcn(x.array(), field, ndim, num_tuples, NULL, tmp_result);
           if (MB_SUCCESS != rval) return rval;
           rval = jacobianFcn(x.array(), verts, nverts, ndim, work, J[0]);
           if (MB_SUCCESS != rval) return rval;
@@ -75,9 +75,11 @@ namespace moab
 
     ErrorCode LinearQuad::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                          const double *posn, const double *verts, const int nverts, const int ndim,
-                                         const double tol, double *work, double *params, bool *is_inside) 
+                                         const double iter_tol, const double inside_tol, double *work, 
+                                         double *params, bool *is_inside) 
     {
-      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, iter_tol, inside_tol, work, 
+                                       params, is_inside);
     } 
 
     bool LinearQuad::insideFcn(const double *params, const int ndim, const double tol) 

diff --git a/src/LocalDiscretization/LinearTet.cpp b/src/LocalDiscretization/LinearTet.cpp
index 705dbee..4965cfc 100644
--- a/src/LocalDiscretization/LinearTet.cpp
+++ b/src/LocalDiscretization/LinearTet.cpp
@@ -74,27 +74,29 @@ namespace moab
     
     ErrorCode LinearTet::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                         const double *posn, const double *verts, const int nverts, const int ndim,
-                                        const double tol, double *work, double *params, bool *is_inside) 
+                                        const double iter_tol, const double inside_tol, double *work, 
+                                        double *params, bool *is_inside) 
     {
       assert(posn && verts);
-      return evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, iter_tol, inside_tol, 
+                              work, params, is_inside);
     } 
 
     bool LinearTet::insideFcn(const double *params, const int , const double tol) 
     {
       return (params[0] >= -1.0-tol && params[1] >= -1.0-tol && params[2] >= -1.0-tol && 
-              params[0] + params[1] + params[2] <= -1.0+tol);
+              params[0] + params[1] + params[2] <= 1.0+tol);
       
     }
     
     ErrorCode LinearTet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
                                           const double *posn, const double *verts, const int nverts, 
-                                          const int ndim, const double tol, double *work, 
-                                          double *params, bool *inside) {
+                                          const int ndim, const double iter_tol, const double inside_tol,
+                                          double *work, double *params, bool *inside) {
         // TODO: should differentiate between epsilons used for
         // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
         // right now, fix the tolerance used for NR
-      const double error_tol_sqr = tol*tol;
+      const double error_tol_sqr = iter_tol*iter_tol;
       CartVect *cvparams = reinterpret_cast<CartVect*>(params);
       const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
 
@@ -138,7 +140,7 @@ namespace moab
       }
 
       if (inside)
-        *inside = (*inside_f)(params, ndim, tol);
+        *inside = (*inside_f)(params, ndim, inside_tol);
 
       return MB_SUCCESS;
     }// Map::evaluate_reverse()

diff --git a/src/LocalDiscretization/LinearTri.cpp b/src/LocalDiscretization/LinearTri.cpp
new file mode 100644
index 0000000..8fe9d23
--- /dev/null
+++ b/src/LocalDiscretization/LinearTri.cpp
@@ -0,0 +1,145 @@
+#include "moab/LinearTri.hpp"
+#include "moab/Forward.hpp"
+#include <algorithm>
+
+namespace moab 
+{
+    
+    const double LinearTri::corner[3][2] = { {0,0},
+                                             {1,0},
+                                             {0,1}};
+
+    ErrorCode LinearTri::initFcn(const double *verts, const int /*nverts*/, double *&work) {
+        // allocate work array as: 
+        // work[0..8] = T
+        // work[9..17] = Tinv
+        // work[18] = detT
+        // work[19] = detTinv
+      assert(!work && verts);
+      work = new double[20];
+      Matrix3 *T = reinterpret_cast<Matrix3*>(work),
+          *Tinv = reinterpret_cast<Matrix3*>(work+9);
+      double *detT = work+18, *detTinv = work+19;
+      
+      *T = Matrix3(verts[1*3+0]-verts[0*3+0],verts[2*3+0]-verts[0*3+0],0.0,
+                   verts[1*3+1]-verts[0*3+1],verts[2*3+1]-verts[0*3+1],0.0,
+                   verts[1*3+2]-verts[0*3+2],verts[2*3+2]-verts[0*3+2],1.0);
+      *T *= 0.5;
+      (*T)(2,2) = 1.0;
+      
+      *Tinv = T->inverse();
+      *detT = T->determinant();
+      *detTinv = (0.0 == *detT ? HUGE : 1.0 / *detT);
+
+      return MB_SUCCESS;
+    }
+
+    ErrorCode LinearTri::evalFcn(const double *params, const double *field, const int /*ndim*/, const int num_tuples, 
+                                 double */*work*/, double *result) {
+      assert(params && field && num_tuples > 0);
+        // convert to [0,1]
+      double p1 = 0.5 * (1.0 + params[0]),
+          p2 = 0.5 * (1.0 + params[1]),
+          p0 = 1.0 - p1 - p2;
+      
+      for (int j = 0; j < num_tuples; j++)
+        result[j] = p0 * field[0*num_tuples+j] + p1 * field[1*num_tuples+j] + p2 * field[2*num_tuples+j];
+
+      return MB_SUCCESS;
+    }
+
+    ErrorCode LinearTri::integrateFcn(const double *field, const double */*verts*/, const int /*nverts*/, const int /*ndim*/, const int num_tuples,
+                                      double *work, double *result) 
+    {
+      assert(field && num_tuples > 0);
+      double tmp = work[18];
+      
+      for (int i = 0; i < num_tuples; i++) 
+        result[i] = tmp * (field[num_tuples+i] + field[2*num_tuples+i]);
+
+      return MB_SUCCESS;
+    }
+
+    ErrorCode LinearTri::jacobianFcn(const double *, const double *, const int, const int , 
+                                     double *work, double *result) 
+    {
+        // jacobian is cached in work array
+      assert(work);
+      std::copy(work, work+9, result);
+      return MB_SUCCESS;
+    }
+    
+    ErrorCode LinearTri::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
+                                        const double *posn, const double *verts, const int nverts, const int ndim,
+                                        const double iter_tol, const double inside_tol, double *work, 
+                                        double *params, bool *is_inside) 
+    {
+      assert(posn && verts);
+      return evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, iter_tol, inside_tol, work, 
+                              params, is_inside);
+    } 
+
+    bool LinearTri::insideFcn(const double *params, const int , const double tol) 
+    {
+      return (params[0] >= -1.0-tol && params[1] >= -1.0-tol &&
+              params[0] + params[1] <= 1.0+tol);
+      
+    }
+    
+    ErrorCode LinearTri::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
+                                          const double *posn, const double *verts, const int nverts, 
+                                          const int ndim, const double iter_tol, const double inside_tol,
+                                          double *work, double *params, bool *inside) {
+        // TODO: should differentiate between epsilons used for
+        // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
+        // right now, fix the tolerance used for NR
+      const double error_tol_sqr = iter_tol*iter_tol;
+      CartVect *cvparams = reinterpret_cast<CartVect*>(params);
+      const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
+
+        // find best initial guess to improve convergence
+      CartVect tmp_params[] = {CartVect(-1,-1,-1), CartVect(1,-1,-1), CartVect(-1,1,-1)};
+      double resl = HUGE;
+      CartVect new_pos, tmp_pos;
+      ErrorCode rval;
+      for (unsigned int i = 0; i < 3; i++) {
+        rval = (*eval)(tmp_params[i].array(), verts, ndim, 3, work, tmp_pos.array());
+        if (MB_SUCCESS != rval) return rval;
+        double tmp_resl = (tmp_pos-*cvposn).length_squared();
+        if (tmp_resl < resl) {
+          *cvparams = tmp_params[i];
+          new_pos = tmp_pos;
+          resl = tmp_resl;
+        }        
+      }
+
+        // residual is diff between old and new pos; need to minimize that
+      CartVect res = new_pos - *cvposn;
+      Matrix3 J;
+      rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);
+      double det = J.determinant();
+      assert(det > std::numeric_limits<double>::epsilon());
+      Matrix3 Ji = J.inverse(1.0/det);
+
+      int iters=0;
+        // while |res| larger than tol
+      while (res % res > error_tol_sqr) {
+        if(++iters>25)
+          return MB_FAILURE;
+
+          // new params tries to eliminate residual
+        *cvparams -= Ji * res;
+
+          // get the new forward-evaluated position, and its difference from the target pt
+        rval = (*eval)(params, verts, ndim, 3, work, new_pos.array());
+        if (MB_SUCCESS != rval) return rval;
+        res = new_pos - *cvposn;
+      }
+
+      if (inside)
+        *inside = (*inside_f)(params, ndim, inside_tol);
+
+      return MB_SUCCESS;
+    }// Map::evaluate_reverse()
+
+} // namespace moab

diff --git a/src/LocalDiscretization/Makefile.am b/src/LocalDiscretization/Makefile.am
index 7309aef..cb34071 100644
--- a/src/LocalDiscretization/Makefile.am
+++ b/src/LocalDiscretization/Makefile.am
@@ -17,6 +17,7 @@ MOAB_LOCALDISCR_SRCS = \
 	LinearHex.cpp \
 	LinearQuad.cpp \
 	LinearTet.cpp \
+	LinearTri.cpp \
 	QuadraticHex.cpp
 
 MOAB_LOCALDISCR_HDRS = \
@@ -24,6 +25,7 @@ MOAB_LOCALDISCR_HDRS = \
 	moab/LinearHex.hpp \
 	moab/LinearQuad.hpp \
 	moab/LinearTet.hpp \
+	moab/LinearTri.hpp \
 	moab/QuadraticHex.hpp
 
 # The list of source files, and any header files that do not need to be installed

diff --git a/src/LocalDiscretization/QuadraticHex.cpp b/src/LocalDiscretization/QuadraticHex.cpp
index ca4758b..5c621f6 100644
--- a/src/LocalDiscretization/QuadraticHex.cpp
+++ b/src/LocalDiscretization/QuadraticHex.cpp
@@ -107,10 +107,12 @@ namespace moab
 
     ErrorCode QuadraticHex::reverseEvalFcn(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                            const double *posn, const double *verts, const int nverts, const int ndim,
-                                           const double tol, double *work, double *params, bool *is_inside) 
+                                           const double iter_tol, const double inside_tol, double *work, 
+                                           double *params, bool *is_inside) 
     {
       assert(posn && verts);
-      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, tol, work, params, is_inside);
+      return EvalSet::evaluate_reverse(eval, jacob, ins, posn, verts, nverts, ndim, iter_tol, inside_tol, 
+                                       work, params, is_inside);
     } 
 
     bool QuadraticHex::insideFcn(const double *params, const int ndim, const double tol) 

diff --git a/src/LocalDiscretization/SpectralHex.cpp b/src/LocalDiscretization/SpectralHex.cpp
index 0e40eba..31f5391 100644
--- a/src/LocalDiscretization/SpectralHex.cpp
+++ b/src/LocalDiscretization/SpectralHex.cpp
@@ -73,7 +73,8 @@ CartVect SpectralHex::evaluate( const CartVect& params ) const
   return result;
 }
   // replicate the functionality of hex_findpt
-bool SpectralHex::evaluate_reverse(CartVect const & xyz, CartVect &params, double tol, const CartVect &init) const
+    bool SpectralHex::evaluate_reverse(CartVect const & xyz, CartVect &params, double iter_tol, const double inside_tol,
+                                       const CartVect &init) const
 {
   params = init;
       
@@ -92,7 +93,7 @@ bool SpectralHex::evaluate_reverse(CartVect const & xyz, CartVect &params, doubl
     //copy parametric coords back
   params = r;
 
-  return is_inside(params, tol);
+  return is_inside(params, inside_tol);
 }
 Matrix3  SpectralHex::jacobian(const CartVect& params) const
 {

diff --git a/src/LocalDiscretization/SpectralQuad.cpp b/src/LocalDiscretization/SpectralQuad.cpp
index cbd1251..5c11d13 100644
--- a/src/LocalDiscretization/SpectralQuad.cpp
+++ b/src/LocalDiscretization/SpectralQuad.cpp
@@ -95,7 +95,8 @@ CartVect SpectralQuad::evalFcn(const double *params, const double *field, const
 }
   // replicate the functionality of hex_findpt
 bool SpectralQuad::reverseEvalFcn(const double *posn, const double *verts, const int nverts, const int ndim,
-                                  const double tol, double *work, double *params, bool *is_inside)
+                                  const double iter_tol, const double inside_tol, double *work, 
+                                  double *params, bool *is_inside)
 {
   params = init;
 
@@ -114,7 +115,7 @@ bool SpectralQuad::reverseEvalFcn(const double *posn, const double *verts, const
     //copy parametric coords back
   params = r;
 
-  return insideFcn(params, 2, tol);
+  return insideFcn(params, 2, inside_tol);
 }
 
 

diff --git a/src/LocalDiscretization/moab/ElemEvaluator.hpp b/src/LocalDiscretization/moab/ElemEvaluator.hpp
index 48d34ac..29d1051 100644
--- a/src/LocalDiscretization/moab/ElemEvaluator.hpp
+++ b/src/LocalDiscretization/moab/ElemEvaluator.hpp
@@ -25,7 +25,8 @@ namespace moab {
 
     typedef ErrorCode (*ReverseEvalFcn)(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
                                         const double *posn, const double *verts, const int nverts, const int ndim,
-                                        const double tol, double *work, double *params, bool *is_inside);
+                                        const double iter_tol, const double inside_tol, 
+                                        double *work, double *params, bool *is_inside);
         
     class EvalSet
     {
@@ -76,8 +77,8 @@ namespace moab {
         /** \brief Common function to do reverse evaluation based on evaluation and jacobian functions */
       static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
                                         const double *posn, const double *verts, const int nverts, 
-                                        const int ndim, const double tol, double *work, double *params, 
-                                        bool *inside);
+                                        const int ndim, const double iter_tol, const double inside_tol, 
+                                        double *work, double *params, bool *inside);
         /** \brief Common function that returns true if params is in [-1,1]^ndims */
       static bool inside_function(const double *params, const int ndims, const double tol);
     };
@@ -119,9 +120,9 @@ namespace moab {
          * \param impl MOAB instance
          * \param ent Entity handle to cache on the evaluator
          * \param tag Tag to cache on the evaluator
-         * \param tag_dim Tag dimension to cache on the evaluator
+         * \param tagged_ent_dim Dimension of entities to be tagged to cache on the evaluator
          */
-      ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tag_dim = -1);
+      ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tagged_ent_dim = -1);
 
         /** \brief Evaluate cached tag at a given parametric location within the cached entity 
          * If evaluating coordinates, call set_tag(0, 0), which indicates coords instead of a tag.
@@ -133,12 +134,14 @@ namespace moab {
         
         /** \brief Reverse-evaluate the cached entity at a given physical position
          * \param posn Position at which to evaluate parameters
-         * \param tol Tolerance of reverse evaluation, usually 10^-6 or so
+         * \param iter_tol Tolerance of reverse evaluation non-linear iteration, usually 10^-10 or so
+         * \param inside_tol Tolerance of is_inside evaluation, usually 10^-6 or so
          * \param params Result of evaluation
          * \param is_inside If non-NULL, returns true of resulting parameters place the point inside the element
          *                  (in most cases, within [-1]*(dim)
          */
-      ErrorCode reverse_eval(const double *posn, double tol, double *params, bool *is_inside = NULL) const;
+      ErrorCode reverse_eval(const double *posn, double iter_tol, double inside_tol, double *params, 
+                             bool *is_inside = NULL) const;
         
         /** \brief Evaluate the jacobian of the cached entity at a given parametric location
          * \param params Parameters at which to evaluate jacobian
@@ -166,14 +169,16 @@ namespace moab {
          * object is changed.
          * \param entities Entities tested
          * \param point Point tested, must have 3 dimensions, even for edge and face entities
-         * \param tol Tolerance for is_inside test
+         * \param iter_tol Tolerance for non-linear reverse evaluation
+         * \param inside_tol Tolerance for is_inside test
          * \param containing_ent Entity containing the point, returned 0 if no entity
          * \param params Parameters of point in containing entity, unchanged if no containing entity
          * \param num_evals If non-NULL, incremented each time reverse_eval is called
          * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
          * reason for failure)
          */
-      ErrorCode find_containing_entity(Range &entities, const double *point, double tol, 
+      ErrorCode find_containing_entity(Range &entities, const double *point, 
+                                       const double iter_tol, const double inside_tol, 
                                        EntityHandle &containing_ent, double *params, 
                                        unsigned int *num_evals = NULL);
       
@@ -186,14 +191,16 @@ namespace moab {
          * object is changed.
          * \param ent_set Entity set containing the entities to be tested
          * \param point Point tested, must have 3 dimensions, even for edge and face entities
-         * \param tol Tolerance for is_inside test
+         * \param iter_tol Tolerance for non-linear reverse evaluation
+         * \param inside_tol Tolerance for is_inside test
          * \param containing_ent Entity containing the point, returned 0 if no entity
          * \param params Parameters of point in containing entity, unchanged if no containing entity
          * \param num_evals If non-NULL, incremented each time reverse_eval is called
          * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
          * reason for failure)
          */
-      ErrorCode find_containing_entity(EntityHandle ent_set, const double *point, double tol, 
+      ErrorCode find_containing_entity(EntityHandle ent_set, const double *point, 
+                                       const double iter_tol, const double inside_tol,
                                        EntityHandle &containing_ent, double *params, 
                                        unsigned int *num_evals = NULL);
       
@@ -218,8 +225,12 @@ namespace moab {
       inline ErrorCode set_ent_handle(EntityHandle ent);
 
         /** \brief Get entity handle for this ElemEval */
-      inline EntityHandle get_ent_handle() const {return entHandle;};
+      inline EntityHandle get_ent_handle() const {return entHandle;}
 
+        /* \brief Get vertex positions cached on this EE
+         */
+      inline double *get_vert_pos() {return vertPos[0].array();}
+      
         /* \brief Get the vertex handles cached here */
       inline const EntityHandle *get_vert_handles() const {return vertHandles;}
 
@@ -233,24 +244,29 @@ namespace moab {
          * To designate that vertex coordinates are the desired tag, pass in a tag handle of 0
          * and a tag dimension of 0.
          * \param tag Tag handle to cache, or 0 to cache vertex positions
-         * \param tag_dim Dimension of entities tagged with this tag
+         * \param tagged_ent_dim Dimension of entities tagged with this tag
          */
-      inline ErrorCode set_tag_handle(Tag tag, int tag_dim = -1);
+      inline ErrorCode set_tag_handle(Tag tag, int tagged_ent_dim = -1);
 
         /* \brief Set the name of the tag to cache on this evaluator
          * To designate that vertex coordinates are the desired tag, pass in "COORDS" as the name
          * and a tag dimension of 0.
-         * \param tag Tag handle to cache, or 0 to cache vertex positions
-         * \param tag_dim Dimension of entities tagged with this tag
+         * \param tag_name Tag handle to cache, or 0 to cache vertex positions
+         * \param tagged_ent_dim Dimension of entities tagged with this tag
          */
-      inline ErrorCode set_tag(const char *tag_name, int ent_dim = -1);
+      inline ErrorCode set_tag(const char *tag_name, int tagged_ent_dim = -1);
       
         /* \brief Get the dimension of the entities on which tag is set */
-      inline int get_tag_dim() const {return tagDim;};
+      inline int get_tagged_ent_dim() const {return taggedEntDim;};
 
         /* \brief Set the dimension of entities having the tag */
-      inline ErrorCode set_tag_dim(int dim);
+      inline ErrorCode set_tagged_ent_dim(int dim);
 
+        /* \brief Get work space, sometimes this is useful for evaluating data you don't want to set as tags on entities
+         * Can't be const because most of the functions (evaluate, integrate, etc.) take non-const work space *'s
+         */
+      inline double *get_work_space() {return workSpace;}
+            
         /* \brief MOAB interface cached on this evaluator */
       inline Interface *get_moab() {return mbImpl;}
       
@@ -287,7 +303,7 @@ namespace moab {
       int numTuples;
 
         /** \brief Dimension of entities from which to grab tag */
-      int tagDim;
+      int taggedEntDim;
 
         /** \brief Tag space */
       std::vector<unsigned char> tagSpace;
@@ -300,13 +316,13 @@ namespace moab {
 
     }; // class ElemEvaluator
 
-    inline ElemEvaluator::ElemEvaluator(Interface *impl, EntityHandle ent, Tag tag, int tag_dim) 
+    inline ElemEvaluator::ElemEvaluator(Interface *impl, EntityHandle ent, Tag tag, int tagged_ent_dim) 
             : mbImpl(impl), entHandle(0), entType(MBMAXTYPE), entDim(-1), numVerts(0), 
               vertHandles(NULL), tagHandle(0), tagCoords(false), numTuples(0), 
-              tagDim(0), workSpace(NULL)
+              taggedEntDim(0), workSpace(NULL)
     {
       if (ent) set_ent_handle(ent);
-      if (tag) set_tag_handle(tag, tag_dim);
+      if (tag) set_tag_handle(tag, tagged_ent_dim);
     }
     
     inline ErrorCode ElemEvaluator::set_ent_handle(EntityHandle ent) 
@@ -329,18 +345,17 @@ namespace moab {
         rval = set_tag_handle(tagHandle);
         if (MB_SUCCESS != rval) return rval;
       }
-
       if (evalSets[entType].initFcn) return (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
       return MB_SUCCESS;
     }
     
-    inline ErrorCode ElemEvaluator::set_tag_handle(Tag tag, int tag_dim) 
+    inline ErrorCode ElemEvaluator::set_tag_handle(Tag tag, int tagged_ent_dim) 
     {
       ErrorCode rval = MB_SUCCESS;
-      if (!tag && !tag_dim) {
+      if (!tag && !tagged_ent_dim) {
         tagCoords = true;
         numTuples = 3;
-        tagDim = 0;
+        taggedEntDim = 0;
         tagHandle = 0;
         return rval;
       }
@@ -355,14 +370,14 @@ namespace moab {
         tagCoords = false;
       }
 
-      tagDim = (-1 == tag_dim ? 0 : tag_dim);
+      taggedEntDim = (-1 == tagged_ent_dim ? 0 : tagged_ent_dim);
       
       if (entHandle) {
-        if (0 == tagDim) {
+        if (0 == taggedEntDim) {
           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
           if (MB_SUCCESS != rval) return rval;
         }
-        else if (tagDim == entDim) {
+        else if (taggedEntDim == entDim) {
           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
           if (MB_SUCCESS != rval) return rval;
         }
@@ -371,14 +386,14 @@ namespace moab {
       return rval;
     }
 
-    inline ErrorCode ElemEvaluator::set_tag(const char *tag_name, int tag_dim) 
+    inline ErrorCode ElemEvaluator::set_tag(const char *tag_name, int tagged_ent_dim) 
     {
       ErrorCode rval = MB_SUCCESS;
       if (!tag_name || strlen(tag_name) == 0) return MB_FAILURE;
       Tag tag;
       if (!strcmp(tag_name, "COORDS")) {
         tagCoords = true;
-        tagDim = 0;
+        taggedEntDim = 0;
         numTuples = 3;
         tagHandle = 0;
           // can return here, because vertex coords already cached when entity handle set
@@ -399,15 +414,15 @@ namespace moab {
           tagCoords = false;
         }
 
-        tagDim = (-1 == tag_dim ? entDim : tag_dim);
+        taggedEntDim = (-1 == tagged_ent_dim ? entDim : tagged_ent_dim);
       }
       
       if (entHandle) {
-        if (0 == tagDim) {
+        if (0 == taggedEntDim) {
           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
           if (MB_SUCCESS != rval) return rval;
         }
-        else if (tagDim == entDim) {
+        else if (taggedEntDim == entDim) {
           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
           if (MB_SUCCESS != rval) return rval;
         }
@@ -431,16 +446,17 @@ namespace moab {
       assert(entHandle && MBMAXTYPE != entType);
       return (*evalSets[entType].evalFcn)(params, 
                                           (tagCoords ? (const double*) vertPos[0].array(): (const double*)&tagSpace[0]), 
-                                          entDim, (-1 == num_tuples ? numTuples : num_tuples), 
-                                          workSpace, result);
+                                          entDim, 
+                                          (-1 == num_tuples ? numTuples : num_tuples), workSpace, result);
     }
         
-    inline ErrorCode ElemEvaluator::reverse_eval(const double *posn, const double tol, double *params, bool *ins) const
+    inline ErrorCode ElemEvaluator::reverse_eval(const double *posn, const double iter_tol, const double inside_tol,
+                                                 double *params, bool *ins) const
     {
       assert(entHandle && MBMAXTYPE != entType);
       return (*evalSets[entType].reverseEvalFcn)(evalSets[entType].evalFcn, evalSets[entType].jacobianFcn, evalSets[entType].insideFcn,
-                                                 posn, vertPos[0].array(), numVerts, entDim, tol, workSpace, 
-                                                 params, ins);
+                                                 posn, vertPos[0].array(), numVerts, 
+                                                 entDim, iter_tol, inside_tol, workSpace, params, ins);
     }
         
       /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
@@ -456,7 +472,7 @@ namespace moab {
       assert(entHandle && MBMAXTYPE != entType && (tagCoords || tagHandle));
       ErrorCode rval = MB_SUCCESS;
       if (!tagCoords) {
-        if (0 == tagDim) rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, (void*)&tagSpace[0]);
+        if (0 == taggedEntDim) rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, (void*)&tagSpace[0]);
         else rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, (void*)&tagSpace[0]);
         if (MB_SUCCESS != rval) return rval;
       }
@@ -465,7 +481,8 @@ namespace moab {
                                                workSpace, result);
     }
 
-    inline ErrorCode ElemEvaluator::find_containing_entity(EntityHandle ent_set, const double *point, double tol, 
+    inline ErrorCode ElemEvaluator::find_containing_entity(EntityHandle ent_set, const double *point, 
+                                                           const double iter_tol, const double inside_tol,
                                                            EntityHandle &containing_ent, double *params, 
                                                            unsigned int *num_evals) 
     {
@@ -473,7 +490,7 @@ namespace moab {
       Range entities;
       ErrorCode rval = mbImpl->get_entities_by_handle(ent_set, entities);
       if (MB_SUCCESS != rval) return rval;
-      else return find_containing_entity(entities, point, tol, containing_ent, params, num_evals);
+      else return find_containing_entity(entities, point, iter_tol, inside_tol, containing_ent, params, num_evals);
     }
         
     inline bool ElemEvaluator::inside(const double *params, const double tol) const 

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/fathomteam/moab/commits/a10295c53dfa/
Changeset:   a10295c53dfa
Branch:      master
User:        danwu
Date:        2014-01-09 20:06:24
Summary:     Merged fathomteam/moab into master
Affected #:  7 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/SpatialLocator.cpp b/src/SpatialLocator.cpp
index f765ab9..36016c1 100644
--- a/src/SpatialLocator.cpp
+++ b/src/SpatialLocator.cpp
@@ -72,7 +72,7 @@ namespace moab
       locTable.enableWriteAccess();
 
         // pass storage directly into locate_points, since we know those arrays are contiguous
-      ErrorCode rval = locate_points(pos, num_points, locTable.vul_wr, locTable.vr_wr, NULL, rel_iter_tol, abs_iter_tol,
+      ErrorCode rval = locate_points(pos, num_points, (EntityHandle*)locTable.vul_wr, locTable.vr_wr, NULL, rel_iter_tol, abs_iter_tol,
                                      inside_tol);
       std::fill(locTable.vi_wr, locTable.vi_wr+num_points, 0);
       locTable.set_n(num_points);

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:

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