diff --git a/nrn/ball_and_stick.py b/nrn/ball_and_stick.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce857fc1a103ab20e00e2b2a60ade74ecffa7de9
--- /dev/null
+++ b/nrn/ball_and_stick.py
@@ -0,0 +1,84 @@
+from neuron import h, gui
+import numpy as np
+
+soma = h.Section(name='soma')
+dend = h.Section(name='dend')
+
+dend.connect(soma(1))
+
+h.psection(sec=soma)
+
+# Surface area of cylinder is 2*pi*r*h (sealed ends are implicit).
+# Here we make a square cylinder in that the diameter
+# is equal to the height, so diam = h. ==> Area = 4*pi*r^2
+# We want a soma of 500 microns squared:
+# r^2 = 500/(4*pi) ==> r = 6.2078, diam = 12.6157
+soma.L = soma.diam = 12.6157 # Makes a soma of 500 microns squared.
+dend.L = 200 # microns
+dend.diam = 1 # microns
+print "Surface area of soma =", h.area(0.5, sec=soma)
+
+for sec in h.allsec():
+    sec.Ra = 100    # Axial resistance in Ohm * cm
+    sec.cm = 1      # Membrane capacitance in micro Farads / cm^2
+
+# Insert active Hodgkin-Huxley current in the soma
+soma.insert('hh')
+soma.gnabar_hh = 0.12  # Sodium conductance in S/cm2
+soma.gkbar_hh = 0.036  # Potassium conductance in S/cm2
+soma.gl_hh = 0.0003    # Leak conductance in S/cm2
+soma.el_hh = -54.3     # Reversal potential in mV
+
+# Insert passive current in the dendrite
+dend.insert('pas')
+dend.g_pas = 0.001  # Passive conductance in S/cm2
+dend.e_pas = -65    # Leak reversal potential mV
+
+#for sec in h.allsec():
+#    h.psection(sec=sec)
+
+stim = h.IClamp(dend(1))
+stim.delay = 5
+stim.dur = 1
+stim.amp = 5*0.1
+
+somastyles = ['b-', 'r-']
+dendstyles = ['b-.', 'r-.']
+dt = [0.02, 0.001]
+nsegs = [10, 100]
+from matplotlib import pyplot
+pyplot.figure(figsize=(8,4)) # Default figsize is (8,6)
+pyplot.grid()
+pos = 0
+for pos in [0] :
+    dend.nseg=nsegs[pos]
+
+    v_soma = h.Vector()        # Membrane potential vector
+    v_dend = h.Vector()        # Membrane potential vector
+    t_vec = h.Vector()        # Time stamp vector
+    v_soma.record(soma(0.5)._ref_v)
+    v_dend.record(dend(1.0)._ref_v)
+    t_vec.record(h._ref_t)
+    simdur = 25.0
+
+    h.tstop = simdur
+    h.dt = dt[pos]
+    h.run()
+
+    pyplot.plot(t_vec, v_soma, somastyles[pos], linewidth=2)
+    pyplot.plot(t_vec, v_dend, dendstyles[pos], linewidth=2)
+
+pyplot.xlabel('time (ms)')
+pyplot.ylabel('mV')
+
+data = np.loadtxt('../tests/v.dat')
+t = data[:,0]
+nfields = data.shape[1]
+
+v = data[:,1]
+pyplot.plot(t, v, 'g', linewidth=2)
+v = data[:,2]
+pyplot.plot(t, v, 'g-.', linewidth=2)
+
+pyplot.show()
+
diff --git a/nrn/nest_soma.py b/nrn/nest_soma.py
new file mode 100644
index 0000000000000000000000000000000000000000..4acec3ed5cb1ac670abc58acc6099dc1dbf696ed
--- /dev/null
+++ b/nrn/nest_soma.py
@@ -0,0 +1,23 @@
+import os.path
+from matplotlib import pyplot
+import numpy as np
+
+step = 0
+while os.path.isfile('../tests/v_' + str(step) + '.dat') :
+    fname = '../tests/v_' + str(step) + '.dat'
+    print 'loading ' + fname
+    data = np.loadtxt(fname)
+    t = data[:,0]
+    v = data[:,1]
+    pyplot.plot(t, v, 'b', label=fname)
+    step = step + 1
+
+pyplot.xlabel('time (ms)')
+pyplot.ylabel('mV')
+
+pyplot.xlim([87.5,89.5])
+#pyplot.ylim([0,40])
+
+pyplot.legend()
+pyplot.show()
+
diff --git a/nrn/soma.py b/nrn/soma.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8912c4f7a0ea6bc204695cbef683b01e5172e44
--- /dev/null
+++ b/nrn/soma.py
@@ -0,0 +1,67 @@
+import os.path
+from neuron import h, gui
+from matplotlib import pyplot
+import numpy as np
+
+soma = h.Section(name='soma')
+
+soma.L = soma.diam = 18.8
+soma.Ra = 123
+
+print "Surface area of soma =", h.area(0.5, sec=soma)
+
+soma.insert('hh')
+
+stim = h.IClamp(soma(0.5))
+stim.delay = 10
+stim.dur = 100
+stim.amp = 0.1
+
+v_vec = h.Vector()        # Membrane potential vector
+t_vec = h.Vector()        # Time stamp vector
+v_vec.record(soma(0.5)._ref_v)
+t_vec.record(h._ref_t)
+simdur = 120
+
+# initialize plot
+pyplot.figure(figsize=(8,4)) # Default figsize is (8,6)
+
+pyplot.subplot(2,1,1)
+pyplot.grid()
+
+h.tstop = simdur
+
+# run neuron with multiple dt
+
+for dt in [0.02, 0.01, 0.005, 0.002, 0.001]:
+    h.dt = dt
+    h.run()
+    pyplot.plot(t_vec, v_vec, label='neuron ' + str(dt))
+    #pyplot.plot(t_vec, v_vec, 'k', label='neuron ' + str(dt))
+
+pyplot.xlim([102.5,105])
+pyplot.ylim([0,40])
+
+pyplot.legend()
+pyplot.subplot(2,1,2)
+pyplot.grid()
+step = 0
+while os.path.isfile('../tests/v_' + str(step) + '.dat') :
+    fname = '../tests/v_' + str(step) + '.dat'
+    print 'loading ' + fname
+    data = np.loadtxt(fname)
+    t = data[:,0]
+    v = data[:,1]
+    #pyplot.plot(t, v, 'b', label=fname)
+    pyplot.plot(t, v, label=fname)
+    step = step + 1
+
+pyplot.xlabel('time (ms)')
+pyplot.ylabel('mV')
+
+pyplot.xlim([102.5,105])
+pyplot.ylim([0,40])
+
+pyplot.legend()
+pyplot.show()
+
diff --git a/src/fvm.hpp b/src/fvm.hpp
index c69f76289a07b6061c2586eb37a84115507575ce..19b27c45268f8be09a4d10e9a79adf2a5d714ac6 100644
--- a/src/fvm.hpp
+++ b/src/fvm.hpp
@@ -434,6 +434,8 @@ void fvm_cell<T, I>::setup_matrix(T dt)
 template <typename T, typename I>
 void fvm_cell<T, I>::initialize()
 {
+    t_ = 0.;
+
     // initialize mechanism states
     for(auto& m : mechanisms_) {
         m->nrn_init();
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 918e00d667a8014783d84473fd59776ad81705ac..4cc842363ad1474e408f7b44e9bb717197bb33fb 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -8,10 +8,10 @@ set(HEADERS
     ../src/tree.hpp
 )
 
-set(TEST_SOURCES
-    # google test framework
-    gtest-all.cpp
+# google test framework
+add_library(gtest gtest-all.cpp gtest.h)
 
+set(TEST_SOURCES
     # unit tests
     test_algorithms.cpp
     test_cell.cpp
@@ -26,14 +26,29 @@ set(TEST_SOURCES
     test_tree.cpp
 
     # unit test driver
-    main.cpp
+    test.cpp
+)
+
+set(VALIDATION_SOURCES
+    # unit tests
+    validate_soma.cpp
+
+    # unit test driver
+    validate.cpp
 )
 
 add_executable(test.exe ${TEST_SOURCES} ${HEADERS})
+add_executable(validate.exe ${VALIDATION_SOURCES} ${HEADERS})
 
-target_link_libraries(test.exe LINK_PUBLIC cellalgo)
+target_link_libraries(test.exe LINK_PUBLIC cellalgo gtest)
+target_link_libraries(validate.exe LINK_PUBLIC cellalgo gtest)
 
 set_target_properties(test.exe
    PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
 )
+
+set_target_properties(validate.exe
+   PROPERTIES
+   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
+)
diff --git a/tests/main.cpp b/tests/test.cpp
similarity index 100%
rename from tests/main.cpp
rename to tests/test.cpp
diff --git a/tests/test_run.cpp b/tests/test_run.cpp
index 82ac6fd452039bfb7f3d703c4145f5bc8601a931..41f17ab5187c640093352eea88e20dae018c78a3 100644
--- a/tests/test_run.cpp
+++ b/tests/test_run.cpp
@@ -1,40 +1,18 @@
 #include <fstream>
 
 #include "gtest.h"
+#include "util.hpp"
 
 #include "../src/cell.hpp"
 #include "../src/fvm.hpp"
 
-void write_vis_file(const std::string& fname, std::vector<std::vector<double>> values)
-{
-    auto m = values.size();
-    if(!m) return;
-
-    std::ofstream fid(fname);
-    if(!fid.is_open()) return;
-
-    auto n = values[0].size();
-    for(const auto& v : values) {
-        std::cout << n << " ----- " << v.size() << "\n";
-        if(n!=v.size()) {
-            std::cerr << "all output arrays must have the same length\n";
-            return;
-        }
-    }
-
-    for(auto i=0u; i<n; ++i) {
-        for(auto j=0u; j<m; ++j) {
-            fid << " " << values[j][i];
-        }
-        fid << "\n";
-    }
-}
-
 // based on hh/Neuron/steps_A.py
 TEST(run, single_compartment)
 {
     using namespace nest::mc;
 
+    std::vector<std::vector<double>> results(2);
+
     nest::mc::cell cell;
 
     // setup global state for the mechanisms
@@ -46,7 +24,8 @@ TEST(run, single_compartment)
     soma->add_mechanism(hh_parameters());
 
     // add stimulus to the soma
-    cell.add_stimulus({0,0}, {5., 3., 0.1});
+    //cell.add_stimulus({0,0}, {5., 3., 0.1});
+    cell.add_stimulus({0,0.5}, {10., 100., 0.1});
 
     // make the lowered finite volume cell
     fvm::fvm_cell<double, int> model(cell);
@@ -57,31 +36,26 @@ TEST(run, single_compartment)
     model.initialize(); // have to do this _after_ initial conditions are set
 
     // run the simulation
-    auto dt     =   0.025; // ms
-    auto tfinal =   25.; // ms
+    auto dt     =   0.0005; // ms
+    auto tfinal =   120.; // ms
     int nt = tfinal/dt;
-    std::vector<double> result;
-    result.push_back(model.voltage()[0]);
+    results[0].push_back(0.);
+    results[1].push_back(model.voltage()[0]);
     for(auto i=0; i<nt; ++i) {
         model.advance(dt);
-        result.push_back(model.voltage()[0]);
+        // save voltage at soma
+        results[0].push_back((i+1)*dt);
+        results[1].push_back(model.voltage()[0]);
     }
 
-    {
-        std::ofstream fid("v.dat");
-        auto t = 0.;
-        for(auto v:result) {
-            fid << t << " " << v << "\n";
-            t += dt;
-        }
-    }
+    write_vis_file("v.dat", results);
 }
 
 TEST(run, ball_and_stick)
 {
     using namespace nest::mc;
 
-    std::vector<std::vector<double>> results(4);
+    std::vector<std::vector<double>> results(3);
 
     nest::mc::cell cell;
 
@@ -94,12 +68,14 @@ TEST(run, ball_and_stick)
 
     // add dendrite of length 200 um and diameter 1 um with passive channel
     auto dendrite = cell.add_cable(0, segmentKind::dendrite, 0.5, 0.5, 200);
-    dendrite->set_compartments(81); // 5 compartments
+    dendrite->set_compartments(10);
     dendrite->add_mechanism(pas_parameters());
 
+    dendrite->mechanism("membrane").set("r_L", 100); // no effect for single compartment cell
+
     // add stimulus
-    //cell.add_stimulus({0,0}, {5., 3., 0.1}); // soma
-    cell.add_stimulus({1,1}, {5., 30., 0.1});
+    //cell.add_stimulus({0,0}, {5., 1., 0.1}); // soma
+    cell.add_stimulus({1,1}, {5., 1., 0.5});
 
     // make the lowered finite volume cell
     fvm::fvm_cell<double, int> model(cell);
@@ -112,19 +88,18 @@ TEST(run, ball_and_stick)
     model.initialize(); // have to do this _after_ initial conditions are set
 
     // run the simulation
-    auto dt = 0.02; // ms
+    auto pos = model.size()-1;
+    auto dt = 0.001; // ms
     auto tfinal = 25.; // ms
     int nt = tfinal/dt;
     results[0].push_back(0.);
     results[1].push_back(model.voltage()[0]);
-    results[2].push_back(model.voltage()[10]);
-    results[3].push_back(model.voltage()[20]);
+    results[2].push_back(model.voltage()[pos]);
     for(auto i=0; i<nt; ++i) {
         model.advance(dt);
         results[0].push_back((i+1)*dt);
         results[1].push_back(model.voltage()[0]);
-        results[2].push_back(model.voltage()[10]);
-        results[3].push_back(model.voltage()[20]);
+        results[2].push_back(model.voltage()[pos]);
     }
 
     write_vis_file("v.dat", results);
diff --git a/tests/test_tree.cpp b/tests/test_tree.cpp
index 9bb320d1e4cf5f1b0e8b1f5e320384f32935d728..2afcb1ed0e24a2bfb0123ba25abab393f59c9ec4 100644
--- a/tests/test_tree.cpp
+++ b/tests/test_tree.cpp
@@ -232,7 +232,7 @@ TEST(cell_tree, balance) {
         EXPECT_EQ(t.parent(5), 2);
         EXPECT_EQ(t.parent(6), 5);
 
-        t.to_graphviz("cell.dot");
+        //t.to_graphviz("cell.dot");
     }
 }
 
@@ -246,8 +246,7 @@ TEST(cell_tree, json_load)
     for(auto c : range(0,cell_data.size())) {
         std::vector<int> parent_index = cell_data[c]["parent_index"];
         cell_tree tree(parent_index);
-        //tree.to_graphviz("cell_" + std::to_string(c) + ".dot");
-        tree.to_graphviz("cell" + std::to_string(c) + ".dot");
+        //tree.to_graphviz("cell" + std::to_string(c) + ".dot");
     }
 }
 
diff --git a/tests/util.hpp b/tests/util.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cf10847fbf0de27657be11eb54b545538c3799b5
--- /dev/null
+++ b/tests/util.hpp
@@ -0,0 +1,30 @@
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+static
+void write_vis_file(const std::string& fname, std::vector<std::vector<double>> values)
+{
+    auto m = values.size();
+    if(!m) return;
+
+    std::ofstream fid(fname);
+    if(!fid.is_open()) return;
+
+    auto n = values[0].size();
+    for(const auto& v : values) {
+        if(n!=v.size()) {
+            std::cerr << "all output arrays must have the same length\n";
+            return;
+        }
+    }
+
+    for(auto i=0u; i<n; ++i) {
+        for(auto j=0u; j<m; ++j) {
+            fid << " " << values[j][i];
+        }
+        fid << "\n";
+    }
+}
+
diff --git a/tests/validate.cpp b/tests/validate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d814fca1512dd79b22763a4f9a769f2984ca5269
--- /dev/null
+++ b/tests/validate.cpp
@@ -0,0 +1,7 @@
+#include "gtest.h"
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
+
diff --git a/tests/validate_soma.cpp b/tests/validate_soma.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b88c09f40b7426d54b06047cb290c993cb9083d5
--- /dev/null
+++ b/tests/validate_soma.cpp
@@ -0,0 +1,55 @@
+#include <fstream>
+
+#include "gtest.h"
+#include "util.hpp"
+
+#include "../src/cell.hpp"
+#include "../src/fvm.hpp"
+
+// based on hh/Neuron/steps_A.py
+TEST(soma, resolutions)
+{
+    using namespace nest::mc;
+
+    nest::mc::cell cell;
+
+    // setup global state for the mechanisms
+    nest::mc::mechanisms::setup_mechanism_helpers();
+
+    // Soma with diameter 18.8um and HH channel
+    auto soma = cell.add_soma(18.8/2.0);
+    soma->mechanism("membrane").set("r_L", 123); // no effect for single compartment cell
+    soma->add_mechanism(hh_parameters());
+
+    // add stimulus to the soma
+    //cell.add_stimulus({0,0}, {5., 3., 0.1});
+    cell.add_stimulus({0,0.5}, {10., 100., 0.1});
+
+    // make the lowered finite volume cell
+    fvm::fvm_cell<double, int> model(cell);
+
+    auto i =0;
+    for(auto dt : {0.02, 0.01, 0.005, 0.002, 0.001}) {
+        std::vector<std::vector<double>> results(2);
+
+        // set initial conditions
+        using memory::all;
+        model.voltage()(all) = -65.;
+        model.initialize(); // have to do this _after_ initial conditions are set
+
+        // run the simulation
+        auto tfinal =   120.; // ms
+        int nt = tfinal/dt;
+        results[0].push_back(0.);
+        results[1].push_back(model.voltage()[0]);
+        for(auto i=0; i<nt; ++i) {
+            model.advance(dt);
+            // save voltage at soma
+            results[0].push_back((i+1)*dt);
+            results[1].push_back(model.voltage()[0]);
+        }
+        write_vis_file("v_" + std::to_string(i) + ".dat", results);
+        ++i;
+    }
+}
+
diff --git a/tests/vis.py b/tests/vis.py
deleted file mode 100644
index 2a1834819da3f6d1c6e0865ec194c15ce637bb35..0000000000000000000000000000000000000000
--- a/tests/vis.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from matplotlib import pyplot
-import numpy as np
-
-data = np.loadtxt('v.dat')
-t = data[:,0]
-nfields = data.shape[1]
-
-for i in range(1,nfields) :
-    v = data[:,i]
-    pyplot.plot(t, v)
-
-pyplot.xlabel('time (ms)')
-pyplot.ylabel('mV')
-pyplot.grid()
-pyplot.show()
-
-
-#mi = min(v)
-#ma = max(v)
-#rng = (ma-mi)/2 * 1.1
-#mn = 0.5*(mi+ma)
-#pyplot.ylim(mn-rng, mn+rng)