diff --git a/ring.py b/ring.py
index f2071ff..5571b0e 100644
--- a/ring.py
+++ b/ring.py
@@ -47,7 +47,7 @@ def mkcells(self, ncell, nbranch, ncompart, types):
             secpar, segvec = celltypeinfo(type, nbranch, ncompart)
             cell = h.B_BallStick(secpar, segvec)
             self.cells.append(cell)
-            settings.pc.set_gid2node(gid, settings.rank)
+            settings.pc.set_gid2node(gid, settings.pc.id())
             nc = cell.connect2target(None)
             settings.pc.cell(gid, nc)
 
diff --git a/ringtest.py b/ringtest.py
index 0c87f5d..02eecf6 100644
--- a/ringtest.py
+++ b/ringtest.py
@@ -118,20 +118,16 @@ def prun(tstop):
     return runtime, load_balance, avg_comp_time, spk_time, gap_time
 
 
-if __name__ == '__main__':
-
-    ## Create all rings ##
-
-    timeit(None, settings.rank)
-
+def network():
     # create network / ring of cells
     ran = h.Random()
     ran.Random123(0, 1)
     types = shuffle([i % ntype for i in range(ncell * nring)], ran)
     rings = [Ring(ncell, nbranch, ncompart, i * ncell, types) for i in range(nring)]
 
-    timeit("created rings", settings.rank)
+    return rings
 
+def randomize(rings):
     # randomize parameters if asked
     if randomize_parameters:
         from ranparm import cellran
@@ -139,8 +135,18 @@ def prun(tstop):
             for gid in ring.gids:
                 if pc.gid_exists(gid):
                     cellran(gid, ring.nclist)
-        timeit("randomized parameters", settings.rank)
 
+if __name__ == '__main__':
+
+    ## Create all rings ##
+
+    timeit(None, settings.rank)
+
+    rings = network()
+    timeit("created rings", settings.rank)
+    if randomize_parameters:
+        randomize(rings)    
+        timeit("randomized parameters", settings.rank)
 
     ## CoreNEURON setting ##
 
diff --git a/test_submodel.py b/test_submodel.py
new file mode 100644
index 0000000..16771d0
--- /dev/null
+++ b/test_submodel.py
@@ -0,0 +1,70 @@
+# Example of how to construct a model as a series of submodels. Each
+# submodel is built, CoreNEURON data is written, and the submodel
+# is destroyed. This file can be run with
+#    python test_submodel.py -rparm
+# which writes data to the coredat folder. That folder can be compared to
+# the corenrn_data folder written by
+#    mpiexec -n 4 nrniv -python -mpi -rparm -coreneuron -filemode ringtest.py
+#    diff -r coredat corenrn_data
+# Note: -rparm is used for a more substantive test in that all the cells are
+# distinct with different parameters.
+
+# The overall strategy for a ringtest model relies on the fact that it
+# already does parallel setup so that there are pc.nhost() submodels,
+# one built on each rank, pc.id(). This setup did not use pc.nhost() or
+# pc.id() directly but stored those values in the global variables nhost and
+# rank respectively. So it is an easy matter to subvert that slightly and
+# run with a single process and iterate over range(nsubmodel) and for each
+# merely set rank and nhost to the proper values. The one exception to this
+# in the ringtest setup was the call to pc.set_gid2node(gid, rank) which was
+# changed to pc.set_gid2node(gid, pc.id()) since that function requires the
+# true rank of this process to function correctly. The other ringtest
+# transformation that was required was to factor out the ring build and
+# randomization into functions that are callable from here as well as in
+# the original ringtest.py .
+
+from neuron import h
+pc = h.ParallelContext()
+cvode = h.CVode()
+
+import ringtest
+
+def test_submodel(nsubmodel):
+  coredat = "./coredat"
+  cvode.cache_efficient(1)
+  for isubmodel in range(nsubmodel):
+    submodel = build_submodel(isubmodel, nsubmodel) # just like a single rank on an nhost cluster
+    # second arg below when False, means to begin a new files.dat file.
+    #  when True, means to append the groupid information to the existing file.
+    pc.nrncore_write("./coredat",  isubmodel != 0)
+    teardown()
+    submodel = None
+
+    # verify no netcons or sections. Ready to go on to next submodel
+    assert (h.List("NetCon").count() == 0)
+    assert (len([s for s in h.allsec()]) == 0)
+
+def build_submodel(isubmodel, nsubmodel):
+  # fake nhost and rank
+  ringtest.settings.nhost = nsubmodel
+  ringtest.settings.rank = isubmodel
+
+  # broke into two parts to avoid timeit problems.
+  rings= ringtest.network()
+  ringtest.randomize(rings)
+
+  # same initialization as ringtest
+  pc.set_maxstep(10)
+  h.stdinit()
+
+  return rings
+
+def teardown():
+  pc.gid_clear()
+  # delete your NetCons list
+  # delete your Cells list
+  # unfortunately, cannot delete submodel here as there is reference to it
+  # in test_submodel(nsubmodel)
+
+if __name__ == "__main__":
+  test_submodel(4)