diff --git a/Geo/CGNSOptions.h b/Geo/CGNSOptions.h
index fe32ec018ca6dac92928cef22947eefc69254981..3052f8d295d263aeb8b58c78e2b1359fdfbef7c6 100644
--- a/Geo/CGNSOptions.h
+++ b/Geo/CGNSOptions.h
@@ -26,6 +26,8 @@ struct CGNSOptions
                                         // Type of CGNS connectivity description
   std::string baseName;
   std::string zoneName;
+  std::string interfaceName;
+  std::string patchName;
 
   // Default values
   CGNSOptions() :
@@ -33,7 +35,9 @@ struct CGNSOptions
     gridConnectivityLocation(2),  // Assumes Vertex = 2 in cgnslib.h
     connectivityNodeType(Generalized),
     baseName("Base_0"),
-    zoneName("Zone_&I0&")
+    zoneName("Zone_&I0&"),
+    interfaceName("Interface_&I0&"),
+    patchName("Patch_&I&")
   { }
 };
 
diff --git a/Geo/GModelIO_CGNS.cpp b/Geo/GModelIO_CGNS.cpp
index 2670f8392a176a019728a0d644906dd34be1b758..cc69b722e969ad99900d870ad1087776c5a55802 100644
--- a/Geo/GModelIO_CGNS.cpp
+++ b/Geo/GModelIO_CGNS.cpp
@@ -39,6 +39,7 @@
 
 int cgnsErr(const int cgIndexFile = -1)
 {
+  Message::Error("This is a CGNS error\n");
   Message::Error(cg_get_error());
   if(cgIndexFile != -1)
     if(cg_close(cgIndexFile)) Message::Error("Unable to close CGNS file");
@@ -54,6 +55,32 @@ typedef std::map<int, std::vector<GEntity*> > PhysGroupMap;
                                         // Type providing a vector of entities
                                         // for a physical group index
 
+//--Class to gather elements that belong to a partition.  This class mimics a
+//--GEntity class.
+
+class DummyPartitionEntity : public GEntity
+{
+ public:
+  DummyPartitionEntity()
+    : GEntity(0, 0)
+  { }
+
+  // number of types of elements
+  int getNumElementTypes() const { return 1; }
+  void getNumMeshElements(unsigned *const c) const
+  {
+    c[0] += elements.size();
+  }
+
+  // get the start of the array of a type of element
+  MElement *const *getStartElementType(int type) const
+  {
+    return &elements[0];
+  }
+
+  std::vector<MElement*> elements;
+};
+
 //--Class to make C style CGNS name strings act like C++ types
 
 class CGNSNameStr
@@ -169,10 +196,9 @@ struct ElemSortCGNSType
  *============================================================================*/
 
 template <unsigned DIM>
-int write_CGNS_zones(GModel &model, const int zoneDefinition,
-                     const CGNSOptions &options,
-                     const double scalingFactor, const int vectorDim,
-                     const PhysGroupMap &group,
+int write_CGNS_zones(GModel &model, const int zoneDefinition, const int numZone,
+                     const CGNSOptions &options, const double scalingFactor,
+                     const int vectorDim, const PhysGroupMap &group,
                      const int cgIndexFile, const int cgIndexBase);
 
 
@@ -231,69 +257,142 @@ int GModel::writeCGNS(const std::string &name, const int zoneDefinition,
   PhysGroupMap groups[4];               // vector of entities that belong to
                                         // each physical group (in each
                                         // dimension)
+  std::vector<DummyPartitionEntity> partitions;
+                                        // Dummy entities that store the
+                                        // elements in each partition
   int numZone;
-  std::vector<std::vector<MElement*> > zoneElements;
+  int meshDim;
+
+  Msg::Warning("CGNS I/O is at an \"alpha\" software stage");
+
   switch(zoneDefinition) {
   case 1:  // By partition
+
+//--Group the elements of each partition into a dummy entity.  Pointers to the
+//--entities are then made available in groups[DIM][0].
+
     {
       numZone = meshPartitions.size();
-      zoneElements.resize(numZone);
-      for(int i = 0; i != numZone; ++i)
-        zoneElements[i].reserve(getMaxPartitionSize());
-//       typedef GRegion Ent;
-//       Ent *ent;
-//       unsigned numElem[4];
-//       numElem[0] = 0; numElem[1] = 0; numElem[2] = 0; numElem[3] = 0;
-//       ent->getNumMeshElements(numElem);
-//       int nType = ent->getNumTypeElements();
-//       for(int iType = 0; iType != nType; ++iType) {
-//         MElement *const start = ent->getMeshElement
-//           ((iType == 0) ? 0 : numElem[iType-1]);
-//         // Then can loop
-//         const int nElem = numElem[iType];
-//         for(int iElem = 0; iElem != nElem; ++iElem) {
-//         }
-//       }
-
+      if(numZone == 0) zoneDefinition = 0;
+      else {
+        partitions.resize(numZone);
+        for(int i = 0; i != numZone; ++i)
+          partitions[i].elements.reserve(getMaxPartitionSize());
+        unsigned numElem[4];
+        meshDim = getNumMeshElements(numElem);
+        // Load the dummy entities with the elements in each partition
+        switch(meshDim) {
+        case 3:
+          for(riter it = firstRegion(); it != lastRegion(); ++it) {
+            numElem[0] = 0; numElem[1] = 0; numElem[2] = 0; numElem[3] = 0;
+            (*it)->getNumMeshElements(numElem);
+            const int nType = (*it)->getNumElementTypes();
+            for(int iType = 0; iType != nType; ++iType) {
+              MElement *const *element = (*it)->getStartElementType(iType);
+              const int nElem = numElem[iType];
+              for(int iElem = 0; iElem != nElem; ++iElem) {
+                partitions[element[iElem]->getPartition() - 1].elements
+                  .push_back(element[iElem]);
+              }
+            }
+          }
+          break;
+        case 2:
+          for(fiter it = firstFace(); it != lastFace(); ++it) {
+            numElem[0] = 0; numElem[1] = 0; numElem[2] = 0; numElem[3] = 0;
+            (*it)->getNumMeshElements(numElem);
+            const int nType = (*it)->getNumElementTypes();
+            for(int iType = 0; iType != nType; ++iType) {
+              MElement *const *element = (*it)->getStartElementType(iType);
+              const int nElem = numElem[iType];
+              for(int iElem = 0; iElem != nElem; ++iElem) {
+                partitions[element[iElem]->getPartition() - 1].elements
+                  .push_back(element[iElem]);
+              }
+            }
+          }
+          break;
+        default:
+          Message::Error("No mesh elements were found");
+          return 0;
+        }
+        // Place pointers to the entities in the 'groups' object
+        std::vector<GEntity*> &ents = groups[meshDim][0];
+        ents.resize(numZone);
+        for(int iPart = 0; iPart != numZone; ++iPart)
+          ents[iPart] = &partitions[iPart];
+      }
     }
     break;
   case 2:  // By physical
-     break;
-  }
 
 //--Get a list of groups in each dimension and each of the entities in that
-//--group.  The groups will define the zones.  If no 2D or 3D groups exist, just
-//--store all mesh elements in one zone.
+//--group.
 
-  getPhysicalGroups(groups);
-  if(groups[face].size() + groups[region].size() == 0) zoneDefinition = 0;
-  {
+    getPhysicalGroups(groups);
+    if(groups[region].size()) {
+      numZone = groups[region].size();
+      meshDim = 3;
+    }
+    else if(groups[face].size()) {
+      numZone = groups[face].size();
+      meshDim = 2;
+    }
+    else {
+      zoneDefinition = 0;  // Use single zone
+    }
+    break;
+  }
 
-    // If there are no 2D or 3D physical groups, save all elements in one zone.
-    // Pretend that there is one physical group ecompassing all the elements.
-    for(riter it = firstRegion(); it != lastRegion(); ++it)
-      if((*it)->tetrahedra.size() + (*it)->hexahedra.size() +
-         (*it)->prisms.size() + (*it)->pyramids.size() > 0)
-        groups[region][1].push_back(*it);
-    if(!groups[region].size()) {
-      // No 3D elements were found.  Look for 2D elements.
-      for(fiter it = firstFace(); it != lastFace(); ++it)
-        if((*it)->triangles.size() + (*it)->quadrangles.size() > 0)
-          groups[face][1].push_back(*it);
-      if(!groups[face].size()) {
-        Message::Error("No mesh elements were found");
-        return 0;
+//--For a single zone, put all the entities for a dimension into groups[DIM][0]
+
+  if(zoneDefinition == 0) {
+    numZone = 1;
+    unsigned numElem[4];
+    numElem[0] = 0; numElem[1] = 0; numElem[2] = 0; numElem[3] = 0;
+    meshDim = getNumMeshElements(numElem);
+    switch(meshDim) {
+    case 3:
+      {
+        groups[region].clear();
+        std::vector<GEntity*> &ents = groups[region][0];
+        ents.resize(getNumRegions());
+        int iEnt = 0;
+        for(riter it = firstRegion(); it != lastRegion(); ++it)
+          ents[iEnt++] = *it;
+      }
+      break;
+    case 2:
+      {
+        groups[face].clear();
+        std::vector<GEntity*> &ents = groups[face][0];
+        ents.resize(getNumFaces());
+        int iEnt = 0;
+        for(fiter it = firstFace(); it != lastFace(); ++it)
+          ents[iEnt++] = *it;
       }
+      break;
+    default:
+      Message::Error("No mesh elements were found");
+      return 0;
     }
   }
 
+/*--------------------------------------------------------------------*
+ * Summary of three possibilities for the 'zoneDefinition':
+ * 0) single zone: all the entities are placed in physical 0.  All the
+ *    entities form the zone.
+ * 1) defined by partitions:  all the entities are place in physical
+ *    0.  Each entity is a zone.
+ * 2) defined by physicals:  all the entities in a physical form a
+ *    zone.
+ *--------------------------------------------------------------------*/
+
 //--Open the file and get ready to write the zones
 
-  // Will this be a 2D or 3D mesh?
-  int meshDim = 2;
+  // Get the dimension of a vector in the mesh
   int vectorDim = 3;
-  if(groups[region].size()) meshDim = 3;
-  else vectorDim = options.vectorDim;
+  if(meshDim == 2) vectorDim = options.vectorDim;
 
   // open the file
   int cgIndexFile;
@@ -301,7 +400,8 @@ int GModel::writeCGNS(const std::string &name, const int zoneDefinition,
 
   // write the base node
   int cgIndexBase;
-  if(cg_base_write(cgIndexFile, "Base_0000", meshDim, meshDim, &cgIndexBase))
+  if(cg_base_write(cgIndexFile, options.baseName.c_str(), meshDim, meshDim,
+                   &cgIndexBase))
     return cgnsErr();
 
   // write information about who generated the mesh
@@ -311,13 +411,13 @@ int GModel::writeCGNS(const std::string &name, const int zoneDefinition,
   switch(meshDim) {
   case 2:
     MZone<2>::preInit();
-    write_CGNS_zones<2>(*this, zoneDefinition, options, scalingFactor,
+    write_CGNS_zones<2>(*this, zoneDefinition, numZone, options, scalingFactor,
                         vectorDim, groups[face], cgIndexFile, cgIndexBase);
     MZone<2>::postDestroy();
     break;
   case 3:
     MZone<3>::preInit();
-    write_CGNS_zones<3>(*this, zoneDefinition, options, scalingFactor,
+    write_CGNS_zones<3>(*this, zoneDefinition, numZone, options, scalingFactor,
                         vectorDim, groups[region], cgIndexFile, cgIndexBase);
     MZone<3>::postDestroy();
     break;
@@ -438,6 +538,64 @@ void translateElementMSH2CGNS(ElementConnectivity *const zoneElemConn)
   }
 }
 
+/*******************************************************************************
+ *
+ * Routine expand_name
+ *
+ * Purpose
+ * =======
+ *
+ *   Expands variables in a string 's' that are supported by the CGNS I/O.  's'
+ *   is overwritten with the expanded string.
+ *
+ *   - &I[0][%width]% expands into 'index'.  Normally 'index' is assumed to have
+ *     C numbering and therefore 1 is added to it.  Option [0] prevents the
+ *     addition of the one.  Option [%width] sets the width of the index to
+ *     'width' and pads with leading zeros.
+ *   - &N& expands to 'name'.
+ *
+ ******************************************************************************/
+
+void expand_name(std::string &s, const int index, const char *const name)
+{  
+  std::string::size_type r1 = s.find('&');
+  // Look for and replace "&-&" sub-strings
+  while(r1 != std::string::npos) {
+    const std::string::size_type r2 = s.find('&', r1+1);
+    if(r2 == std::string::npos) {
+      s.replace(r1, s.length()-r1, "");
+    }
+    else {
+      const int rn = r2 - r1 + 1;
+      switch(s[r1+1]) {
+      case 'I':
+        // &I[0][%width]&
+        {
+          int iplus = 1;
+          if(s[r1+2] == '0') iplus = 0;
+          char fmt[6] = "%d";
+          const std::string::size_type f = s.find('%', r1+1);
+          if(f != std::string::npos && f < r2) {
+            int w = std::atoi(s.substr(f+1, r2-f-1).c_str());
+            if(w > 0 && w < 33) std::sprintf(fmt, "%%0%dd", w);
+          }
+          s.replace(r1, rn, CGNSNameStr(index+iplus, fmt).c_str());
+          break;
+        }
+      case 'N':
+        // &N&
+        s.replace(r1, rn, name);
+        break;
+      default:
+        s.replace(r1, rn, "");
+      }
+    }
+    if(s.length() > 1024) s = "";  // idiot/recursive check
+    r1 = s.find('&');
+  }
+
+}
+
 
 /*******************************************************************************
  *
@@ -454,71 +612,58 @@ void translateElementMSH2CGNS(ElementConnectivity *const zoneElemConn)
  *
  *   model              - (I) gmsh model
  *   zoneDefinition     - (I) how to define the zone (see enum in code)
+ *   numZone            - (I) Number of zones in the domain
  *   options            - (I) options for CGNS I/O
- *   numPartitions      - (I)
  *   group              - (I) the group of physicals used to define the mesh
  *   globalZoneIndex    - (I/O)
- *   globalParittion    - (I/O)
- *   globalItPhysical   - (I/O) a global scope iterator to the physicals
+ *   globalPhysicalIt   - (I/O) a global scope iterator to the physicals
  *   zoneIndex          - (O) index of the zone
  *   partition          - (O) partition of the zone
- *   itPhysicalBegin    - (O) begin physical for defining the zone
- *   itPhysicalEnd      - (O) end physical for defining the zone
+ *   physicalItBegin    - (O) begin physical for defining the zone
+ *   physicalItEnd      - (O) end physical for defining the zone
  *   zoneName           - (O) name of the zone
  *
  ******************************************************************************/
 
 int get_zone_definition(GModel &model, const int zoneDefinition,
-                        const CGNSOptions &options,
-                        const int numPartitions, const PhysGroupMap &group,
-                        int &globalZoneIndex, int &globalPartition,
-                        PhysGroupMap::const_iterator &globalItPhysical,
+                        const int numZone, const CGNSOptions &options,
+                        const PhysGroupMap &group, int &globalZoneIndex,
+                        PhysGroupMap::const_iterator &globalPhysicalIt,
                         int &zoneIndex, int &partition,
-                        PhysGroupMap::const_iterator &itPhysicalBegin,
-                        PhysGroupMap::const_iterator &itPhysicalEnd,
+                        PhysGroupMap::const_iterator &physicalItBegin,
+                        PhysGroupMap::const_iterator &physicalItEnd,
                         CGNSNameStr &zoneName)
 {
-  enum {
-    DefineZoneSingle = 0,
-    DefineZoneByPartition = 1,
-    DefineZoneByPhysical = 2
-  };
 
   int status = 0;
   const char *_zoneName = "Partition";
 
-//--Get indices for the zone
+//--Get indices for the zonex
 
 #pragma omp critical (get_zone_definition)
   {
-    switch(zoneDefinition) {
-    case DefineZoneSingle:
-      if(globalZoneIndex > 0) status = 1;  // No more zones
-      else {
+    if(globalZoneIndex >= numZone) status = 1;
+    else {
+      switch(zoneDefinition) {
+      case 0:  // Single zone
         partition = -1;
-        itPhysicalBegin = group.begin();
-        itPhysicalEnd = group.end();
-      }
-      break;
-    case DefineZoneByPartition:
-      if(globalPartition > numPartitions) status = 1;   // No more zones
-      else {
-        partition = globalPartition++;
-        itPhysicalBegin = group.begin();
-        itPhysicalEnd = group.end();
-      }
-      break;
-    case DefineZoneByPhysical:
-      if(globalItPhysical == group.end()) status = 1;  // No more zones
-      else {
+        physicalItBegin = group.begin();
+        physicalItEnd = group.end();
+        break;
+      case 1:  // Zone defined by partition
+        partition = globalZoneIndex;
+        physicalItBegin = group.begin();
+        physicalItEnd = group.end();
+        break;
+      case 2:  // Zone defined by physical
         partition = -1;
-        _zoneName = model.getPhysicalName(globalItPhysical->first).c_str();
-        itPhysicalBegin = globalItPhysical++;
-        itPhysicalEnd = globalItPhysical;
+        _zoneName = model.getPhysicalName(globalPhysicalIt->first).c_str();
+        physicalItBegin = globalPhysicalIt++;
+        physicalItEnd = globalPhysicalIt;
+        break;
       }
-      break;
+      zoneIndex = globalZoneIndex++;
     }
-    zoneIndex = globalZoneIndex++;
   }
 //omp: end critical
 
@@ -526,41 +671,7 @@ int get_zone_definition(GModel &model, const int zoneDefinition,
 
   if(status == 0) {
     std::string s = options.zoneName;
-    std::string::size_type r1 = s.find('&');
-    // Look for and replace "&&" sub-strings
-    while(r1 != std::string::npos) {
-      const std::string::size_type r2 = s.find('&', r1+1);
-      if(r2 == std::string::npos) {
-        s.replace(r1, s.length()-r1, "");
-      }
-      else {
-        const int rn = r2 - r1 + 1;
-        switch(s[r1+1]) {
-        case 'I':
-          // &I[0][%width]&
-          {
-            int iplus = 1;
-            if(s[r1+2] == '0') iplus = 0;
-            char fmt[6] = "%d";
-            const std::string::size_type f = s.find('%', r1+1);
-            if(f != std::string::npos && f < r2) {
-              int w = std::atoi(s.substr(f+1, r2-f-1).c_str());
-              if(w > 0 && w < 33) std::sprintf(fmt, "%%0%dd", w);
-            }
-            s.replace(r1, rn, CGNSNameStr(zoneIndex+iplus, fmt).c_str());
-            break;
-          }
-        case 'N':
-          // &N&
-          s.replace(r1, rn, _zoneName);
-          break;
-        default:
-          s.replace(r1, rn, "");
-        }
-      }
-      if(s.length() > 1024) s = "";  // idiot/recursive check
-      r1 = s.find('&');
-    }
+    expand_name(s, zoneIndex, _zoneName);
     if(s.length() == 0) {  // If empty
       s = "Zone_";
       s += CGNSNameStr(zoneIndex+1).c_str();
@@ -569,6 +680,7 @@ int get_zone_definition(GModel &model, const int zoneDefinition,
   }
 
   return status;
+
 }
 
 
@@ -633,26 +745,23 @@ struct ZoneInfo
 };
 
 template <unsigned DIM>
-int write_CGNS_zones(GModel &model, const int zoneDefinition,
-                     const CGNSOptions &options,
-                     const double scalingFactor, const int vectorDim,
-                     const PhysGroupMap &group,
+int write_CGNS_zones(GModel &model, const int zoneDefinition, const int numZone,
+                     const CGNSOptions &options, const double scalingFactor,
+                     const int vectorDim, const PhysGroupMap &group,
                      const int cgIndexFile, const int cgIndexBase)
 {
 
 //--Shared data
 
-  const int numPartitions = model.getMeshPartitions().size();
   int threadsWorking = omp_get_num_threads();
                                         // Semaphore for working threads
   omp_lock_t threadWLock;
   std::queue<ZoneTask<DIM>*> zoneQueue; // Queue for zones that have been
                                         // defined and are ready to be written
   omp_lock_t queueLock;
-  // Next 3 are locked by omp critical
+  // Next two are locked by an omp critical
   int globalZoneIndex = 0;
-  int globalPartition = 1;
-  PhysGroupMap::const_iterator globalItPhysical = group.begin();
+  PhysGroupMap::const_iterator globalPhysicalIt = group.begin();
 
 //--Initialize omp locks
 
@@ -676,7 +785,7 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
       std::vector<double> dBuffer;      // Buffer for double-precision data
       std::vector<int> iBuffer1, iBuffer2;
                                         // Buffers for integer data
-      int indexInterface = 0;           // Index for interfaces
+      int interfaceIndex = 0;           // Index for interfaces
 
       while (threadsWorking || zoneQueue.size()) {
         if (zoneQueue.size()) {
@@ -700,8 +809,6 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
                            writeTask->zoneName.c_str(), cgZoneSize,
                            Unstructured, &cgIndexZone))
             return cgnsErr();
-//           std::cout << "Zone size: " << cgZoneSize[0] << ' '  // DBG
-//                     << cgZoneSize[1] << ' ' << cgZoneSize[2] << std::endl;
           // Manually maintain the size of the 'zoneInfo vector'.  'push_back'
           // is not used because the elements are in order of 'zoneIndex'
           if(writeTask->zoneIndex >= zoneInfo.size())
@@ -794,22 +901,26 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
               iBuffer2[iVert] = vp.vertexIndex2;
             }
             int cgIndexInterface;
+            std::string interfaceName = options.interfaceName;
+            expand_name(interfaceName, interfaceIndex++, "Interface");
+            if(interfaceName.length() == 0) {
+              interfaceName = "Interface_";
+              interfaceName += CGNSNameStr(interfaceIndex).c_str();
+            }
             // In the first zone
             if(cg_conn_write
                (cgIndexFile, cgIndexBase, zoneInfo[gCIt->first.zone1].cgIndex,
-                CGNSNameStr(++indexInterface, "Interface_%d").c_str(), Vertex,
-                Abutting1to1, PointList, nVert, &iBuffer1[0],
-                zoneInfo[gCIt->first.zone2].name.c_str(), Unstructured,
-                PointListDonor, Integer, nVert, &iBuffer2[0],
+                interfaceName.c_str(), Vertex, Abutting1to1, PointList, nVert,
+                &iBuffer1[0], zoneInfo[gCIt->first.zone2].name.c_str(),
+                Unstructured, PointListDonor, Integer, nVert, &iBuffer2[0],
                 &cgIndexInterface))
               return cgnsErr();
             // In the second zone
             if(cg_conn_write
                (cgIndexFile, cgIndexBase, zoneInfo[gCIt->first.zone2].cgIndex,
-                CGNSNameStr(++indexInterface, "Interface_%d").c_str(), Vertex,
-                Abutting1to1, PointList, nVert, &iBuffer2[0],
-                zoneInfo[gCIt->first.zone1].name.c_str(), Unstructured,
-                PointListDonor, Integer, nVert, &iBuffer1[0],
+                interfaceName.c_str(), Vertex, Abutting1to1, PointList, nVert,
+                &iBuffer2[0], zoneInfo[gCIt->first.zone1].name.c_str(),
+                Unstructured, PointListDonor, Integer, nVert, &iBuffer1[0],
                 &cgIndexInterface))
               return cgnsErr();
           }
@@ -830,15 +941,14 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
  *--------------------------------------------------------------------*/
 
         else {
-          PhysGroupMap::const_iterator itPhysicalBegin;
-          PhysGroupMap::const_iterator itPhysicalEnd;
+          PhysGroupMap::const_iterator physicalItBegin;
+          PhysGroupMap::const_iterator physicalItEnd;
           int zoneIndex;
           int partition;
           if(get_zone_definition
-             (model, zoneDefinition, options, numPartitions, group,
-              globalZoneIndex, globalPartition, globalItPhysical,
-              zoneTask.zoneIndex, partition, itPhysicalBegin, itPhysicalEnd,
-              zoneTask.zoneName)) {
+             (model, zoneDefinition, numZone, options, group, globalZoneIndex,
+              globalPhysicalIt, zoneTask.zoneIndex, partition, physicalItBegin,
+              physicalItEnd, zoneTask.zoneName)) {
             omp_set_lock(&threadWLock);
             --threadsWorking;
             omp_unset_lock(&threadWLock);
@@ -846,14 +956,21 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
           else {
             zoneTask.zone.clear();
             // Loop through all physical in the zone definition
-            for(PhysGroupMap::const_iterator itPhysical = itPhysicalBegin;
-                itPhysical != itPhysicalEnd; ++itPhysical) {
+            for(PhysGroupMap::const_iterator physicalIt = physicalItBegin;
+                physicalIt != physicalItEnd; ++physicalIt) {
               // Add elements from all entities in the physical with defined
               // partition number
-              zoneTask.zone.template add_elements_in_entities
-                <typename std::vector<GEntity*>::const_iterator>
-                (itPhysical->second.begin(), itPhysical->second.end(),
-                 partition);
+              if(partition == -1) {
+                zoneTask.zone.template add_elements_in_entities
+                  <typename std::vector<GEntity*>::const_iterator>
+                  (physicalIt->second.begin(), physicalIt->second.end());
+              }
+              else {
+                zoneTask.zone.template add_elements_in_entities
+                  <typename std::vector<GEntity*>::const_iterator>
+                  (physicalIt->second.begin() + partition,
+                   physicalIt->second.begin() + (partition+1));
+              }
             }
             // Process the zone
             zoneTask.zone.zoneData();
@@ -904,9 +1021,14 @@ int write_CGNS_zones(GModel &model, const int zoneDefinition,
           const int numBCVert = iVert - iVertStart;
 
           int cgIndexBoco;
+          std::string patchName = options.patchName;
+          expand_name(patchName, patchIndex-1, "Patch");
+          if(patchName.length() == 0) {
+            patchName = "Patch_";
+            patchName += CGNSNameStr(patchIndex).c_str();
+          }
           if(cg_boco_write(cgIndexFile, cgIndexBase,
-                           zoneInfo[zoneIndex].cgIndex,
-                           CGNSNameStr(patchIndex, "Patch %d").c_str(),
+                           zoneInfo[zoneIndex].cgIndex, patchName.c_str(),
                            BCTypeNull, PointList, numBCVert, &iBuffer1[0],
                            &cgIndexBoco))
             return cgnsErr();
diff --git a/Geo/MZoneBoundary.cpp b/Geo/MZoneBoundary.cpp
index 648a814b1c8814d22279290752b1dc07643f5d1e..07223536945934f4152bcf4c71ffaf7481dcaf87 100644
--- a/Geo/MZoneBoundary.cpp
+++ b/Geo/MZoneBoundary.cpp
@@ -187,6 +187,7 @@ void updateBoVec
  * ===
  *
  *   vertex             - (I) The vertex to find the normal at
+ *   zoneIndex          - (I) Zone being worked on
  *   edge               - (I) The geometry edge upon which the vertex resides
  *                            and from which the normal will be determined
  *   faces              - (I) All faces on the boundary connected to 'vertex'
@@ -197,10 +198,11 @@ void updateBoVec
  *============================================================================*/
 
 int edge_normal
-(const MVertex *const vertex, const GEdge *const gEdge,
+(const MVertex *const vertex, const int zoneIndex, const GEdge *const gEdge,
  const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB>
  &faces, SVector3 &boNormal)
 {
+
   const double par = gEdge->parFromPoint(vertex->point());
   if(par == std::numeric_limits<double>::max()) return 1;
 
@@ -210,17 +212,22 @@ int edge_normal
   SVector3 meshPlaneNormal(0.);         // This normal is perpendicular to the
                                         // plane of the mesh
 
-  // The interior point and mesh plane normal are computed from all elements.
+  // The interior point and mesh plane normal are computed from all elements in
+  // the zone.
+  int cFace = 0;
   const int nFace = faces.size();
   for(int iFace = 0; iFace != nFace; ++iFace) {
-    interior += faces[iFace].parentElement->barycenter();
-    // Make sure all the planes go in the same direction
-    //**Required?
-    SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
-    if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
-    meshPlaneNormal += mpnt;
+    if(faces[iFace].zoneIndex == zoneIndex) {
+      ++cFace;
+      interior += faces[iFace].parentElement->barycenter();
+      // Make sure all the planes go in the same direction
+      //**Required?
+      SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
+      if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
+      meshPlaneNormal += mpnt;
+    }
   }
-  interior /= nFace;
+  interior /= cFace;
   // Normal to the boundary edge (but unknown direction)
   boNormal = crossprod(tangent, meshPlaneNormal);
   boNormal.normalize();
@@ -229,6 +236,7 @@ int edge_normal
   if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.)
     boNormal.negate();
   return 0;
+
 }
 
 
@@ -244,8 +252,6 @@ void updateBoVec<2, MEdge>
  const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB>
  &faces, ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem)
 {
-  SVector3 boNormal;                    // Normal to the boundary face (edge in
-                                        // 2D)
 
   GEntity *const ent = vertex->onWhat();
   if(ent == 0) {
@@ -274,7 +280,7 @@ void updateBoVec<2, MEdge>
         for(int iFace = 0; iFace != nFace; ++iFace) {
           if(zoneIndex == faces[iFace].zoneIndex) {
             MEdge mEdge = faces[iFace].parentElement->getEdge
-              (faces[iFace].parentFace);
+                (faces[iFace].parentFace);
             // Get the other vertex on the mesh edge.
             MVertex *vertex2 = mEdge.getMinVertex();
             if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex();
@@ -282,7 +288,9 @@ void updateBoVec<2, MEdge>
             // is also connected to vertex.  If so, add it to the container of
             // edge entities that will be used to determine the normal
             GEntity *const ent2 = vertex2->onWhat();
-            if(ent2->dim() == 1) useGEdge.push_back(static_cast<GEdge*>(ent2));
+            if(ent2->dim() == 1) {
+              useGEdge.push_back(static_cast<GEdge*>(ent2));
+            }
           }
         }
 
@@ -292,14 +300,17 @@ void updateBoVec<2, MEdge>
         switch(useGEdge.size()) {
 
         case 0:
-          goto getNormalFromElements;
+//           goto getNormalFromElements;
+          // We probably don't want BC data if none of the faces attatched to
+          // this vertex and in this zone are on the boundary.
+          break;
 
         case 1:
           {
             const GEdge *const gEdge =
               static_cast<const GEdge*>(useGEdge[0]);
             SVector3 boNormal;
-            if(edge_normal(vertex, gEdge, faces, boNormal))
+            if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal))
                goto getNormalFromElements;
             zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(),
                                                boNormal,
@@ -315,14 +326,14 @@ void updateBoVec<2, MEdge>
             const GEdge *const gEdge1 =
               static_cast<const GEdge*>(useGEdge[0]);
             SVector3 boNormal1;
-            if(edge_normal(vertex, gEdge1, faces, boNormal1))
+            if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1))
               goto getNormalFromElements;
 
             // Get the second normal
             const GEdge *const gEdge2 =
               static_cast<const GEdge*>(useGEdge[1]);
             SVector3 boNormal2;
-            if(edge_normal(vertex, gEdge2, faces, boNormal2))
+            if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2))
               goto getNormalFromElements;
 
             if(dot(boNormal1, boNormal2) < 0.98) {
@@ -371,7 +382,8 @@ void updateBoVec<2, MEdge>
 
       {
         SVector3 boNormal;
-        if(edge_normal(vertex, static_cast<const GEdge*>(ent), faces, boNormal))
+        if(edge_normal(vertex, zoneIndex, static_cast<const GEdge*>(ent), faces,
+                       boNormal))
           goto getNormalFromElements;
         zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal,
                                            const_cast<MVertex*>(vertex),
@@ -405,11 +417,13 @@ void updateBoVec<2, MEdge>
                                         // plane of the mesh
     const int nFace = faces.size();
     for(int iFace = 0; iFace != nFace; ++iFace) {
+      if(faces[iFace].zoneIndex == zoneIndex) {
       // Make sure all the planes go in the same direction
       //**Required?
-      SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
-      if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
-      meshPlaneNormal += mpnt;
+        SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal();
+        if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate();
+        meshPlaneNormal += mpnt;
+      }
     }
     // Sum the normals from each element.  The tangent is computed from all
     // faces in the zone attached to the vertex and is weighted by the length of
@@ -417,7 +431,7 @@ void updateBoVec<2, MEdge>
     // inwards-pointing normal.
     SVector3 boNormal(0.);
     for(int iFace = 0; iFace != nFace; ++iFace) {
-      if(zoneIndex == faces[iFace].zoneIndex) {
+      if(faces[iFace].zoneIndex == zoneIndex) {
         const SVector3 tangent = faces[iFace].parentElement->getEdge
           (faces[iFace].parentFace).tangent();
         // Normal to the boundary (unknown direction)
@@ -599,15 +613,20 @@ void updateBoVec<3, MFace>
         for(std::list<const GFace*>::const_iterator gFIt = useGFace.begin();
             gFIt != useGFace.end(); ++gFIt) {
           const SPoint2 par = (*gFIt)->parFromPoint(vertex->point());
-          if(par.x() == std::numeric_limits<double>::max())
+          if(par.x() == std::numeric_limits<double>::max())  //**?
             goto getNormalFromElements;  // :P  After all that!
 
           SVector3 boNormal = (*gFIt)->normal(par);
           SPoint3 interior(0., 0., 0.);
+          int cFace = 0;
           const int nFace = faces.size();
-          for(int iFace = 0; iFace != nFace; ++iFace)
-            interior += faces[iFace].parentElement->barycenter();
-          interior /= nFace;
+          for(int iFace = 0; iFace != nFace; ++iFace) {
+            if(faces[iFace].zoneIndex == zoneIndex) {
+              ++cFace;
+              interior += faces[iFace].parentElement->barycenter();
+            }
+          }
+          interior /= cFace;
           if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.)
             boNormal.negate();
 
@@ -633,10 +652,15 @@ void updateBoVec<3, MFace>
 
         SVector3 boNormal = static_cast<const GFace*>(ent)->normal(par);
         SPoint3 interior(0., 0., 0.);
+          int cFace = 0;
         const int nFace = faces.size();
-        for(int iFace = 0; iFace != nFace; ++iFace)
-          interior += faces[iFace].parentElement->barycenter();
-        interior /= nFace;
+        for(int iFace = 0; iFace != nFace; ++iFace) {
+          if(faces[iFace].zoneIndex == zoneIndex) {
+            ++cFace;
+            interior += faces[iFace].parentElement->barycenter();
+          }
+        }
+        interior /= cFace;
         if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.)
           boNormal.negate();
 
@@ -672,14 +696,16 @@ void updateBoVec<3, MFace>
     SVector3 boNormal(0.);
     const int nFace = faces.size();
     for(int iFace = 0; iFace != nFace; ++iFace) {
-      // Normal to the boundary (unknown direction)
-      SVector3 bnt = faces[iFace].parentElement->getFace
-        (faces[iFace].parentFace).normal();
-      // Inwards normal
-      const SVector3 inwards(vertex->point(),
-                             faces[iFace].parentElement->barycenter());
-      if(dot(bnt, inwards) < 0.) bnt.negate();
-      boNormal += bnt;
+      if(faces[iFace].zoneIndex == zoneIndex) {
+        // Normal to the boundary (unknown direction)
+        SVector3 bnt = faces[iFace].parentElement->getFace
+          (faces[iFace].parentFace).normal();
+        // Inwards normal
+        const SVector3 inwards(vertex->point(),
+                               faces[iFace].parentElement->barycenter());
+        if(dot(bnt, inwards) < 0.) bnt.negate();
+        boNormal += bnt;
+      }
     }
     boNormal.normalize();
     zoneBoVec.push_back(VertexBoundary(zoneIndex, 0, boNormal,
@@ -735,6 +761,12 @@ int MZoneBoundary<DIM>::interiorBoundaryVertices
 
 //--Find or insert this vertex into the global map
 
+//     bool debug = false;
+//     if(vMapIt->first->x() == 1. && vMapIt->first->y() == 0.) {
+//       std::cout << "Working with vertex(1, 0): " << vMapIt->first
+//                 << " for zone " << newZoneIndex << std::endl;
+//       debug = true;
+//     }
     std::pair<typename GlobalBoVertexMap::iterator, bool> insGblBoVertMap =
       globalBoVertMap.insert(std::pair<const MVertex*, GlobalVertexData<FaceT> >
                              (vMapIt->first, GlobalVertexData<FaceT>()));
@@ -748,9 +780,21 @@ int MZoneBoundary<DIM>::interiorBoundaryVertices
 
 //--A new vertex was inserted
 
+//       if(debug) {
+//         std::cout << "This vertex is new and has bo faces:\n";
+//       }
       // Copy faces
       const int nFace = zoneVertData.faces.size();
       for(int iFace = 0; iFace != nFace; ++iFace) {
+//         if(debug) {
+//           std::cout << "  ("
+//                     << zoneVertData.faces[iFace]->first.getVertex(0)->x() << ","
+//                     << zoneVertData.faces[iFace]->first.getVertex(0)->y()
+//                     << "), ("
+//                     << zoneVertData.faces[iFace]->first.getVertex(1)->x() << ","
+//                     << zoneVertData.faces[iFace]->first.getVertex(1)->y()
+//                     << ")\n";
+//         }
         globalVertData.faces.push_back
           (typename GlobalVertexData<FaceT>::FaceDataB
            (newZoneIndex, zoneVertData.faces[iFace]));
@@ -781,26 +825,33 @@ int MZoneBoundary<DIM>::interiorBoundaryVertices
       }
 
       // Update the list of faces attached to this vertex
-      const int nGFace = globalVertData.faces.size();
-                                        // This is the maximum number of faces
-                                        // searched from 'globalVertData'.  This
-                                        // size may increase as faces are added
-                                        // and the order may also change as
-                                        // faces are deleted.  However, only the
-                                        // faces before nGFace are important.
+      unsigned nGFace = globalVertData.faces.size();
+                                        // This is the number of faces searched
+                                        // from 'globalVertData'.  It will only
+                                        // decrease if the size() is less.
+                                        // Since a FaceVector swaps the last
+                                        // element into the erased index, this
+                                        // implies that if new faces are added,
+                                        // then old ones deleted, some of the
+                                        // faces from zoneVertData may also be
+                                        // searched.  This is okay since they
+                                        // are all unique.
       const typename MZone<DIM>::BoFaceMap::const_iterator *zFace =
         &zoneVertData.faces[0];
       for(int nZFace = zoneVertData.faces.size(); nZFace--;) {
-        int iGFace = 0;
-        while(iGFace != nGFace) {
+        bool foundMatch = false;
+        for(int iGFace = 0; iGFace != nGFace; ++iGFace) {
           if((*zFace)->first == globalVertData.faces[iGFace].face) {
-            // Faces match - delete from 'globalVertData'
+            foundMatch = true;
+            // Faces match - delete from 'globalVertData'.
             globalVertData.faces.erase(iGFace);
+            // Erasing from the FaceVector swaps the last element into this
+            // index.  We only decrease nGFace if the size is less.
+            nGFace = std::min(globalVertData.faces.size(), nGFace);
             break;
           }
-          ++iGFace;
         }
-        if(iGFace == nGFace) {
+        if(!foundMatch) {
           // New face - add to 'globalVertData'
           globalVertData.faces.push_back
             (typename GlobalVertexData<FaceT>::FaceDataB(newZoneIndex, *zFace));
@@ -812,6 +863,12 @@ int MZoneBoundary<DIM>::interiorBoundaryVertices
       // and it may be deleted.
       if(globalVertData.faces.size() == 0)
         globalBoVertMap.erase(insGblBoVertMap.first);
+      else {
+        // Update the list of zones attached to this vertex
+        globalVertData.zoneData.push_back
+          (typename GlobalVertexData<FaceT>::ZoneData
+           (zoneVertData.index, newZoneIndex));
+      }
     }
   }  // End loop over boundary vertices