diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp
index 1a3065ec1c8d3178ccd0a2374a51948d2bc7be65..00adf7e5723a35f0b009e07e43d29ae49d38c4f0 100644
--- a/miniapp/miniapp.cpp
+++ b/miniapp/miniapp.cpp
@@ -26,7 +26,6 @@
 using namespace nest::mc;
 
 using global_policy = communication::global_policy;
-using communicator_type = communication::communicator<global_policy>;
 
 using lowered_cell = fvm::fvm_cell<double, cell_local_size_type>;
 using model_type = model<lowered_cell>;
diff --git a/miniapp/miniapp_recipes.cpp b/miniapp/miniapp_recipes.cpp
index 8de187b9e2ccf14394c66c208c291aaecec9b7ef..0c8b7a2d7c8c3ebd7aa81c78a554ba823e1462f8 100644
--- a/miniapp/miniapp_recipes.cpp
+++ b/miniapp/miniapp_recipes.cpp
@@ -15,7 +15,12 @@ namespace mc {
 // description for greater data reuse.
 
 template <typename RNG>
-mc::cell make_basic_cell(unsigned compartments_per_segment, unsigned num_synapses, const std::string& syn_type, RNG& rng) {
+cell make_basic_cell(
+    unsigned compartments_per_segment,
+    unsigned num_synapses,
+    const std::string& syn_type,
+    RNG& rng)
+{
     nest::mc::cell cell;
 
     // Soma with diameter 12.6157 um and HH channel
diff --git a/miniapp/trace_sampler.hpp b/miniapp/trace_sampler.hpp
index b0ea4dcb01a44294c409bed1ea2cd4dbd7eeafa6..2e10257a12883e2dd9f8c69d2a2894cdbc001ea6 100644
--- a/miniapp/trace_sampler.hpp
+++ b/miniapp/trace_sampler.hpp
@@ -13,10 +13,10 @@ namespace nest {
 namespace mc {
 
 // move sampler code to another source file...
-template <typename TimeT=float, typename ValueT=double>
+template <typename Time=float, typename Value=double>
 struct sample_trace {
-    using time_type = TimeT;
-    using value_type = ValueT;
+    using time_type = Time;
+    using value_type = Value;
 
     struct sample_type {
         time_type time;
@@ -34,10 +34,10 @@ struct sample_trace {
     {}
 };
 
-template <typename TimeT=float, typename ValueT=double>
+template <typename Time=float, typename Value=double>
 struct trace_sampler {
-    using time_type = TimeT;
-    using value_type = ValueT;
+    using time_type = Time;
+    using value_type = Value;
 
     float next_sample_t() const { return t_next_sample_; }
 
@@ -62,9 +62,9 @@ private:
 };
 
 // with type deduction ...
-template <typename TimeT, typename ValueT>
-trace_sampler<TimeT, ValueT> make_trace_sampler(sample_trace<TimeT, ValueT> *trace, TimeT sample_dt, TimeT tfrom=0) {
-    return trace_sampler<TimeT, ValueT>(trace, sample_dt, tfrom);
+template <typename Time, typename Value>
+trace_sampler<Time, Value> make_trace_sampler(sample_trace<Time, Value> *trace, Time sample_dt, Time tfrom=0) {
+    return trace_sampler<Time, Value>(trace, sample_dt, tfrom);
 }
 
 } // namespace mc
diff --git a/src/catypes.hpp b/src/catypes.hpp
index cf12b768359fd8e673eb77d33c822375c9c09e74..0337c0ac2831f1fde39b56f86d71fa7b6d36129c 100644
--- a/src/catypes.hpp
+++ b/src/catypes.hpp
@@ -20,29 +20,18 @@ using cell_gid_type = std::uint32_t;
 using cell_size_type = typename std::make_unsigned<cell_gid_type>::type;
 
 // for indexes into cell-local data
-using cell_local_index_type = std::uint32_t;
+using cell_lid_type = std::uint32_t;
 
 // for counts of cell-local data
-using cell_local_size_type = typename std::make_unsigned<cell_local_index_type>::type;
+using cell_local_size_type = typename std::make_unsigned<cell_lid_type>::type;
 
 struct cell_member_type {
     cell_gid_type gid;
-    cell_local_index_type index;
+    cell_lid_type index;
 };
 
 DEFINE_LEXICOGRAPHIC_ORDERING(cell_member_type,(a.gid,a.index),(b.gid,b.index))
 
-// good idea? bad idea?
-using packed_cell_member_type = std::uint64_t;
-
-inline packed_cell_member_type pack_cell_member(cell_member_type m) {
-    return ((packed_cell_member_type)m.gid<<32u) + m.index;
-}
-
-inline cell_member_type unpack_cell_member(packed_cell_member_type p) {
-    return {(cell_gid_type)(p>>32u), (cell_local_index_type)(p&((1ull<<32)-1))};
-}
-
 } // namespace mc
 } // namespace nest
 
diff --git a/src/cell.cpp b/src/cell.cpp
index 73e1960b421394336161db7671ec41ff51d18b66..cf4dd478367c318c6a3405eeb61f437fc0b68f46 100644
--- a/src/cell.cpp
+++ b/src/cell.cpp
@@ -77,7 +77,7 @@ cable_segment* cell::add_cable(cell::index_type parent, segment_ptr&& cable)
 
 segment* cell::segment(index_type index)
 {
-    if(index<0 || index>=num_segments()) {
+    if (index>=num_segments()) {
         throw std::out_of_range(
             "attempt to access a segment with invalid index"
         );
@@ -87,7 +87,7 @@ segment* cell::segment(index_type index)
 
 segment const* cell::segment(index_type index) const
 {
-    if(index<0 || index>=num_segments()) {
+    if (index>=num_segments()) {
         throw std::out_of_range(
             "attempt to access a segment with invalid index"
         );
diff --git a/src/cell.hpp b/src/cell.hpp
index 5d01241c5d3d002daff5662d8cd68db6da650bd1..effdf9254a22b1a5db20673544274a0784db9fce 100644
--- a/src/cell.hpp
+++ b/src/cell.hpp
@@ -23,7 +23,7 @@ struct compartment_model {
 };
 
 struct segment_location {
-    segment_location(cell_local_index_type s, double l)
+    segment_location(cell_lid_type s, double l)
     : segment(s), position(l)
     {
         EXPECTS(position>=0. && position<=1.);
@@ -31,7 +31,7 @@ struct segment_location {
     friend bool operator==(segment_location l, segment_location r) {
         return l.segment==r.segment && l.position==r.position;
     }
-    cell_local_index_type segment;
+    cell_lid_type segment;
     double position;
 };
 
@@ -53,9 +53,7 @@ struct probe_spec {
 /// high-level abstract representation of a cell and its segments
 class cell {
 public:
-
-    // types
-    using index_type = cell_local_index_type;
+    using index_type = cell_lid_type;
     using size_type = cell_local_size_type;
     using value_type = double;
     using point_type = point<value_type>;
diff --git a/src/cell_group.hpp b/src/cell_group.hpp
index f667ebdbeabb7ed93f0941bfba076eda45f94296..69a94a98fa3de23890b735a3d52a1c381c70322d 100644
--- a/src/cell_group.hpp
+++ b/src/cell_group.hpp
@@ -119,7 +119,7 @@ public:
         }
     }
 
-    const std::vector<spike<source_id_type>>&
+    const std::vector<spike<source_id_type, time_type>>&
     spikes() const { return spikes_; }
 
     cell_type&       cell()       { return cell_; }
@@ -161,13 +161,13 @@ private:
     std::vector<spike_source_type> spike_sources_;
 
     //. spikes that are generated
-    std::vector<spike<source_id_type>> spikes_;
+    std::vector<spike<source_id_type, time_type>> spikes_;
 
     /// pending events to be delivered
-    event_queue<postsynaptic_spike_event> events_;
+    event_queue<postsynaptic_spike_event<time_type>> events_;
 
     /// pending samples to be taken
-    event_queue<sample_event> sample_events_;
+    event_queue<sample_event<time_type>> sample_events_;
 
     /// the global id of the first target (e.g. a synapse) in this group
     index_type first_target_gid_;
diff --git a/src/cell_tree.hpp b/src/cell_tree.hpp
index 4a5ccf57379b54129f5f0310a74854ecbf025b60..3bbcb3ef4816ea61dcd8702b1587069f342645be 100644
--- a/src/cell_tree.hpp
+++ b/src/cell_tree.hpp
@@ -33,7 +33,7 @@ class cell_tree {
     using range = memory::Range;
 
 public:
-    using int_type        = cell_local_index_type;
+    using int_type        = cell_lid_type;
     using size_type       = cell_local_size_type;
 
     using index_type      = memory::HostVector<int_type>;
diff --git a/src/communication/communicator.hpp b/src/communication/communicator.hpp
index 42dfa845a61b96e9ec5a7bd616bd124124531fd2..cefffd4cfd381c7d2350a2efd1c178d534b1ce1a 100644
--- a/src/communication/communicator.hpp
+++ b/src/communication/communicator.hpp
@@ -26,13 +26,14 @@ namespace communication {
 // Once all connections have been specified, the construct() method can be used
 // to build the data structures required for efficient spike communication and
 // event generation.
-template <typename CommunicationPolicy>
+template <typename Time, typename CommunicationPolicy>
 class communicator {
 public:
     using id_type = cell_gid_type;
+    using time_type = Time;
     using communication_policy_type = CommunicationPolicy;
 
-    using spike_type = spike<cell_member_type>;
+    using spike_type = spike<cell_member_type, time_type>;
 
     communicator() = default;
 
@@ -49,7 +50,7 @@ public:
     }
 
 
-    void add_connection(connection con) {
+    void add_connection(connection<time_type> con) {
         EXPECTS(is_local_cell(con.destination().gid));
         connections_.push_back(con);
     }
@@ -65,8 +66,8 @@ public:
         }
     }
 
-    float min_delay() {
-        auto local_min = std::numeric_limits<float>::max();
+    time_type min_delay() {
+        auto local_min = std::numeric_limits<time_type>::max();
         for (auto& con : connections_) {
             local_min = std::min(local_min, con.delay());
         }
@@ -113,7 +114,7 @@ public:
 
             // generate an event for each target
             for (auto it=targets.first; it!=targets.second; ++it) {
-                auto gidx = it->destination().gid - cell_gid_from_;
+                auto gidx = cell_group_index(it->destination().gid);
                 events_[gidx].push_back(it->make_event(spike));
             }
         }
@@ -126,11 +127,11 @@ public:
 
     uint64_t num_spikes() const { return num_spikes_; }
 
-    const std::vector<postsynaptic_spike_event>& queue(int i) const {
+    const std::vector<postsynaptic_spike_event<time_type>>& queue(int i) const {
         return events_[i];
     }
 
-    const std::vector<connection>& connections() const {
+    const std::vector<connection<time_type>>& connections() const {
         return connections_;
     }
 
@@ -152,7 +153,20 @@ public:
         }
     }
 
+    void reset() {
+        // remove all in-flight spikes/events
+        clear_thread_spike_buffers();
+        for (auto& evbuf: events_) {
+            evbuf.clear();
+        }
+    }
+
 private:
+    std::size_t cell_group_index(cell_gid_type cell_gid) const {
+        // this will be more elaborate when there is more than one cell per cell group
+        EXPECTS(cell_gid>=cell_gid_from_ && cell_gid<cell_gid_to_);
+        return cell_gid-cell_gid_from_;
+    }
 
     //
     //  both of these can be fixed with double buffering
@@ -167,8 +181,8 @@ private:
         nest::mc::threading::enumerable_thread_specific<std::vector<spike_type>>;
     local_spike_store_type thread_spikes_;
 
-    std::vector<connection> connections_;
-    std::vector<std::vector<postsynaptic_spike_event>> events_;
+    std::vector<connection<time_type>> connections_;
+    std::vector<std::vector<postsynaptic_spike_event<time_type>>> events_;
 
     // for keeping track of how time is spent where
     //util::Profiler profiler_;
diff --git a/src/communication/mpi_global_policy.hpp b/src/communication/mpi_global_policy.hpp
index 8ff8e8830dae040ff80cb0a04d77ef8b43d0f67e..54ded32cc059e2bff221a880edbd3ee68c4f272b 100644
--- a/src/communication/mpi_global_policy.hpp
+++ b/src/communication/mpi_global_policy.hpp
@@ -18,10 +18,9 @@ namespace mc {
 namespace communication {
 
 struct mpi_global_policy {
-    using id_type = cell_member_type;
-
-    std::vector<spike<id_type>> 
-    static gather_spikes(const std::vector<spike<id_type>>& local_spikes) {
+    template <typename I, typename T>
+    static std::vector<spike<I, T>>
+    gather_spikes(const std::vector<spike<I,T>>& local_spikes) {
         return mpi::gather_all(local_spikes);
     }
 
diff --git a/src/communication/serial_global_policy.hpp b/src/communication/serial_global_policy.hpp
index d18e91a6550ed3324d5c191e163c790cce77db9d..9af5eae3fd0dd84be71cb6346018c607fa9ab3df 100644
--- a/src/communication/serial_global_policy.hpp
+++ b/src/communication/serial_global_policy.hpp
@@ -4,7 +4,6 @@
 #include <type_traits>
 #include <vector>
 
-#include <catypes.hpp>
 #include <spike.hpp>
 
 namespace nest {
@@ -12,10 +11,9 @@ namespace mc {
 namespace communication {
 
 struct serial_global_policy {
-    using id_type = cell_member_type;
-
-    std::vector<spike<id_type>> const
-    static gather_spikes(const std::vector<spike<id_type>>& local_spikes) {
+    template <typename I, typename T>
+    static const std::vector<spike<I, T>>&
+    gather_spikes(const std::vector<spike<I, T>>& local_spikes) {
         return local_spikes;
     }
 
diff --git a/src/connection.hpp b/src/connection.hpp
index b08bbc88d3c3046f8da3e2185a7b9f4b631d2482..3ef99a9c28e1007c88835b9e1df1be4765bc32f5 100644
--- a/src/connection.hpp
+++ b/src/connection.hpp
@@ -9,11 +9,13 @@
 namespace nest {
 namespace mc {
 
+template <typename Time>
 class connection {
 public:
     using id_type = cell_member_type;
+    using time_type = Time;
 
-    connection(id_type src, id_type dest, float w, float d) :
+    connection(id_type src, id_type dest, float w, time_type d) :
         source_(src),
         destination_(dest),
         weight_(w),
@@ -26,7 +28,7 @@ public:
     id_type source() const { return source_; }
     id_type destination() const { return destination_; }
 
-    postsynaptic_spike_event make_event(spike<id_type> s) {
+    postsynaptic_spike_event<time_type> make_event(spike<id_type, time_type> s) {
         return {destination_, s.time + delay_, weight_};
     }
 
@@ -34,32 +36,32 @@ private:
     id_type source_;
     id_type destination_;
     float weight_;
-    float delay_;
+    time_type delay_;
 };
 
 // connections are sorted by source id
 // these operators make for easy interopability with STL algorithms
 
-static inline
-bool operator< (connection lhs, connection rhs) {
+template <typename T>
+static inline bool operator<(connection<T> lhs, connection<T> rhs) {
     return lhs.source() < rhs.source();
 }
 
-static inline
-bool operator< (connection lhs, connection::id_type rhs) {
+template <typename T>
+static inline bool operator<(connection<T> lhs, typename connection<T>::id_type rhs) {
     return lhs.source() < rhs;
 }
 
-static inline
-bool operator< (connection::id_type lhs, connection rhs) {
+template <typename T>
+static inline bool operator<(typename connection<T>::id_type lhs, connection<T> rhs) {
     return lhs < rhs.source();
 }
 
 } // namespace mc
 } // namespace nest
 
-static inline
-std::ostream& operator<<(std::ostream& o, nest::mc::connection const& con) {
+template <typename T>
+static inline std::ostream& operator<<(std::ostream& o, nest::mc::connection<T> const& con) {
     return o << "con [" << con.source() << " -> " << con.destination()
              << " : weight " << con.weight()
              << ", delay " << con.delay() << "]";
diff --git a/src/event_queue.hpp b/src/event_queue.hpp
index 8d04f9db0a1ecddaf24680c2e75ce00b56a31590..b78cc0ca821aa2d393c64280164adad50f355e74 100644
--- a/src/event_queue.hpp
+++ b/src/event_queue.hpp
@@ -10,20 +10,33 @@
 namespace nest {
 namespace mc {
 
+/* An event class Event must comply with the following conventions:
+ * Typedefs:
+ *     time_type               floating point type used to represent event times
+ * Member functions:
+ *     time_type when() const  return time value associated with event
+ */
+
+template <typename Time>
 struct postsynaptic_spike_event {
+    using time_type = Time;
+
     cell_member_type target;
-    float time;
+    time_type time;
     float weight;
-};
 
-inline float event_time(const postsynaptic_spike_event &ev) { return ev.time; }
+    time_type when() const { return time; }
+};
 
+template <typename Time>
 struct sample_event {
+    using time_type = Time;
+
     std::uint32_t sampler_index;
-    float time;
-};
+    time_type time;
 
-inline float event_time(const sample_event &ev) { return ev.time; }
+    time_type when() const { return time; }
+};
 
 /* Event objects must have a method event_time() which returns a value
  * from a type with a total ordering with respect to <, >, etc.
@@ -33,7 +46,7 @@ template <typename Event>
 class event_queue {
 public :
     using value_type = Event;
-    using time_type = decltype(event_time(std::declval<Event>()));
+    using time_type = typename Event::time_type;
 
     // create
     event_queue() {}
@@ -47,7 +60,7 @@ public :
     }
 
     // push thing
-    void push(const value_type &e) {
+    void push(const value_type& e) {
          queue_.push(e);
     }
 
@@ -57,7 +70,7 @@ public :
 
     // pop until
     util::optional<value_type> pop_if_before(time_type t_until) {
-         if (!queue_.empty() && event_time(queue_.top()) < t_until) {
+         if (!queue_.empty() && queue_.top().when() < t_until) {
              auto ev = queue_.top();
              queue_.pop();
              return ev;
@@ -74,8 +87,8 @@ public :
 
 private:
     struct event_greater {
-        bool operator()(const Event &a, const Event &b) {
-            return event_time(a) > event_time(b);
+        bool operator()(const Event& a, const Event& b) {
+            return a.when() > b.when();
         }
     };
 
@@ -89,8 +102,8 @@ private:
 } // namespace nest
 } // namespace mc
 
-inline
-std::ostream& operator<< (std::ostream& o, const nest::mc::postsynaptic_spike_event& e)
+template <typename T>
+inline std::ostream& operator<<(std::ostream& o, const nest::mc::postsynaptic_spike_event<T>& e)
 {
     return o << "event[" << e.target << "," << e.time << "," << e.weight << "]";
 }
diff --git a/src/fvm_cell.hpp b/src/fvm_cell.hpp
index a613fbee410e447d5947742551486f533546a28c..1717638931be43fde399db56ec1a7210e39616a3 100644
--- a/src/fvm_cell.hpp
+++ b/src/fvm_cell.hpp
@@ -113,7 +113,8 @@ public:
     void advance(value_type dt);
 
     /// pass an event to the appropriate synapse and call net_receive
-    void apply_event(postsynaptic_spike_event e) {
+    template <typename Time>
+    void apply_event(postsynaptic_spike_event<Time> e) {
         mechanisms_[synapse_index_]->net_receive(e.target.index, e.weight);
     }
 
@@ -343,7 +344,7 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell)
 
     synapse_index_ = mechanisms_.size();
 
-    std::map<std::string, std::vector<cell_local_index_type>> syn_map;
+    std::map<std::string, std::vector<cell_lid_type>> syn_map;
     for (const auto& syn : cell.synapses()) {
         syn_map[syn.mechanism.name()].push_back(find_compartment_index(syn.location, graph));
     }
@@ -373,7 +374,7 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell)
                 }
             }
         }
-        std::vector<cell_local_index_type> indexes(index_set.begin(), index_set.end());
+        std::vector<cell_lid_type> indexes(index_set.begin(), index_set.end());
 
         // create the ion state
         if(indexes.size()) {
diff --git a/src/model.hpp b/src/model.hpp
index 252691fdbab57913a75ccfde1dcf19321752f7a3..556121adfb42a4d32aed01c76537e9b78b9febc8 100644
--- a/src/model.hpp
+++ b/src/model.hpp
@@ -16,11 +16,12 @@ namespace nest {
 namespace mc {
 
 template <typename Cell>
-struct model {
+class model {
+public:
     using cell_group_type = cell_group<Cell>;
     using time_type = typename cell_group_type::time_type;
     using value_type = typename cell_group_type::value_type;
-    using communicator_type = communication::communicator<communication::global_policy>;
+    using communicator_type = communication::communicator<time_type, communication::global_policy>;
     using sampler_function = typename cell_group_type::sampler_function;
 
     struct probe_record {
@@ -29,7 +30,9 @@ struct model {
     };
 
     model(const recipe &rec, cell_gid_type cell_from, cell_gid_type cell_to):
-        cell_from_(cell_from), cell_to_(cell_to)
+        cell_from_(cell_from),
+        cell_to_(cell_to),
+        communicator_(cell_from, cell_to)
     {
         cell_groups_ = std::vector<cell_group_type>{cell_to_-cell_from_};
 
@@ -41,7 +44,7 @@ struct model {
                 auto idx = i-cell_from_;
                 cell_groups_[idx] = cell_group_type(i, cell);
 
-                cell_local_index_type j = 0;
+                cell_lid_type j = 0;
                 for (const auto& probe: cell.probes()) {
                     cell_member_type probe_id{i,j++};
                     probes.push_back({probe_id, probe});
@@ -51,23 +54,21 @@ struct model {
 
         probes_.assign(probes.begin(), probes.end());
 
-        communicator_ = communicator_type(cell_from_, cell_to_);
         for (cell_gid_type i=cell_from_; i<cell_to_; ++i) {
             for (const auto& cc: rec.connections_on(i)) {
-                // currently cell_connection and connection are basically the same data;
-                // merge?
-                communicator_.add_connection(connection{cc.source, cc.dest, cc.weight, cc.delay});
+                connection<time_type> conn{cc.source, cc.dest, cc.weight, cc.delay};
+                communicator_.add_connection(conn);
             }
         }
         communicator_.construct();
     }
 
-
     void reset() {
         t_ = 0.;
         for (auto& group: cell_groups_) {
             group.reset();
         }
+        communicator_.reset();
     }
 
     time_type run(time_type tfinal, time_type dt) {
diff --git a/src/spike.hpp b/src/spike.hpp
index 2779738987d62daf5d1da834a5667c79b4e57f58..d3ea02551456d2408712886dcff8125b314630e9 100644
--- a/src/spike.hpp
+++ b/src/spike.hpp
@@ -6,15 +6,17 @@
 namespace nest {
 namespace mc {
 
-template <typename I>
+template <typename I, typename Time>
 struct spike {
     using id_type = I;
+    using time_type = Time;
+
     id_type source = id_type{};
-    float time = -1.;
+    time_type time = -1.;
 
     spike() = default;
 
-    spike(id_type s, float t) :
+    spike(id_type s, time_type t) :
         source(s), time(t)
     {}
 };
@@ -23,15 +25,15 @@ struct spike {
 } // namespace nest
 
 /// custom stream operator for printing nest::mc::spike<> values
-template <typename I>
-std::ostream& operator<<(std::ostream& o, nest::mc::spike<I> s) {
+template <typename I, typename T>
+std::ostream& operator<<(std::ostream& o, nest::mc::spike<I, T> s) {
     return o << "spike[t " << s.time << ", src " << s.source << "]";
 }
 
 /// less than comparison operator for nest::mc::spike<> values
 /// spikes are ordered by spike time, for use in sorting and queueing
-template <typename I>
-bool operator<(nest::mc::spike<I> lhs, nest::mc::spike<I> rhs) {
+template <typename I, typename T>
+bool operator<(nest::mc::spike<I, T> lhs, nest::mc::spike<I, T> rhs) {
     return lhs.time < rhs.time;
 }
 
diff --git a/tests/unit/test_compartments.cpp b/tests/unit/test_compartments.cpp
index c109f9cda9a335ce32f695f85ccd0295446a5d92..3ca0acbcabf995637b77c79173431e34e449617f 100644
--- a/tests/unit/test_compartments.cpp
+++ b/tests/unit/test_compartments.cpp
@@ -15,13 +15,13 @@ TEST(compartments, compartment)
 
     {
         nest::mc::compartment c(100, 1.2, 2.1, 2.2);
-        EXPECT_EQ(c.index, 100);
+        EXPECT_EQ(c.index, 100u);
         EXPECT_EQ(c.length, 1.2);
         EXPECT_EQ(left(c.radius), 2.1);
         EXPECT_EQ(right(c.radius), 2.2);
 
         auto c2 = c;
-        EXPECT_EQ(c2.index, 100);
+        EXPECT_EQ(c2.index, 100u);
         EXPECT_EQ(c2.length, 1.2);
         EXPECT_EQ(left(c2.radius), 2.1);
         EXPECT_EQ(right(c2.radius), 2.2);
@@ -29,7 +29,7 @@ TEST(compartments, compartment)
 
     {
         nest::mc::compartment c{100, 1, 2, 3};
-        EXPECT_EQ(c.index, 100);
+        EXPECT_EQ(c.index, 100u);
         EXPECT_EQ(c.length, 1.);
         EXPECT_EQ(left(c.radius), 2.);
         EXPECT_EQ(right(c.radius), 3.);
@@ -54,7 +54,7 @@ TEST(compartments, compartment_iterator)
     ++it;
     {
         auto c = *it;
-        EXPECT_EQ(c.index, 1);
+        EXPECT_EQ(c.index, 1u);
         EXPECT_EQ(left(c.radius), 3.0);
         EXPECT_EQ(right(c.radius), 5.0);
         EXPECT_EQ(c.length, 2.5);
@@ -65,7 +65,7 @@ TEST(compartments, compartment_iterator)
     // returned iterator should be unchanged
     {
         auto c = *(it++);
-        EXPECT_EQ(c.index, 1);
+        EXPECT_EQ(c.index, 1u);
         EXPECT_EQ(left(c.radius), 3.0);
         EXPECT_EQ(right(c.radius), 5.0);
         EXPECT_EQ(c.length, 2.5);
@@ -73,7 +73,7 @@ TEST(compartments, compartment_iterator)
     // while the iterator itself was updated
     {
         auto c = *it;
-        EXPECT_EQ(c.index, 2);
+        EXPECT_EQ(c.index, 2u);
         EXPECT_EQ(left(c.radius), 5.0);
         EXPECT_EQ(right(c.radius), 7.0);
         EXPECT_EQ(c.length, 2.5);
@@ -84,7 +84,7 @@ TEST(compartments, compartment_iterator)
         // copy iterator
         auto it2 = it;
         auto c = *it2;
-        EXPECT_EQ(c.index, 2);
+        EXPECT_EQ(c.index, 2u);
         EXPECT_EQ(left(c.radius), 5.0);
         EXPECT_EQ(right(c.radius), 7.0);
         EXPECT_EQ(c.length, 2.5);
@@ -96,7 +96,7 @@ TEST(compartments, compartment_iterator)
 
         // check the copy has updated correctly when incremented
         c= *it2;
-        EXPECT_EQ(c.index, 3);
+        EXPECT_EQ(c.index, 3u);
         EXPECT_EQ(left(c.radius), 7.0);
         EXPECT_EQ(right(c.radius), 9.0);
         EXPECT_EQ(c.length, 2.5);
@@ -112,7 +112,7 @@ TEST(compartments, compartment_range)
         EXPECT_EQ((*rng.end()).index, 10);
         EXPECT_NE(rng.begin(), rng.end());
 
-        auto count = 0;
+        int count = 0;
         for(auto c : rng) {
             EXPECT_EQ(c.index, count);
             auto er = 1.0 + double(count)/10.;
diff --git a/tests/unit/test_event_queue.cpp b/tests/unit/test_event_queue.cpp
index 558ac1c293f5f53b3a562481d7193b90031c335f..f4e31b26715fa2aa3cb690720442cc68f2b18fe2 100644
--- a/tests/unit/test_event_queue.cpp
+++ b/tests/unit/test_event_queue.cpp
@@ -7,7 +7,7 @@
 TEST(event_queue, push)
 {
     using namespace nest::mc;
-    using ps_event_queue = event_queue<postsynaptic_spike_event>;
+    using ps_event_queue = event_queue<postsynaptic_spike_event<float>>;
 
     ps_event_queue q;
 
@@ -31,9 +31,9 @@ TEST(event_queue, push)
 TEST(event_queue, push_range)
 {
     using namespace nest::mc;
-    using ps_event_queue = event_queue<postsynaptic_spike_event>;
+    using ps_event_queue = event_queue<postsynaptic_spike_event<float>>;
 
-    postsynaptic_spike_event events[] = {
+    postsynaptic_spike_event<float> events[] = {
         {{1u, 0u}, 2.f, 2.f},
         {{4u, 1u}, 1.f, 2.f},
         {{8u, 2u}, 20.f, 2.f},
@@ -56,7 +56,7 @@ TEST(event_queue, push_range)
 TEST(event_queue, pop_if_before)
 {
     using namespace nest::mc;
-    using ps_event_queue = event_queue<postsynaptic_spike_event>;
+    using ps_event_queue = event_queue<postsynaptic_spike_event<float>>;
 
     cell_member_type target[4] = {
         {1u, 0u},
@@ -65,7 +65,7 @@ TEST(event_queue, pop_if_before)
         {2u, 3u}
     };
 
-    postsynaptic_spike_event events[] = {
+    postsynaptic_spike_event<float> events[] = {
         {target[0], 1.f, 2.f},
         {target[1], 2.f, 2.f},
         {target[2], 3.f, 2.f},
diff --git a/tests/unit/test_fvm.cpp b/tests/unit/test_fvm.cpp
index 99e676cb317fe566142cb2c713b0a83834dd2ee6..ea8cd7dae4f1b2cc17af3c39cfd3422169180dca 100644
--- a/tests/unit/test_fvm.cpp
+++ b/tests/unit/test_fvm.cpp
@@ -41,7 +41,7 @@ TEST(fvm, cable)
     cell.segment(1)->set_compartments(4);
     cell.segment(2)->set_compartments(4);
 
-    using fvm_cell = fvm::fvm_cell<double, cell_local_index_type>;
+    using fvm_cell = fvm::fvm_cell<double, cell_lid_type>;
     fvm_cell fvcell(cell);
     auto& J = fvcell.jacobian();
 
@@ -91,7 +91,7 @@ TEST(fvm, init)
 
     cell.segment(1)->set_compartments(10);
 
-    using fvm_cell = fvm::fvm_cell<double, cell_local_index_type>;
+    using fvm_cell = fvm::fvm_cell<double, cell_lid_type>;
     fvm_cell fvcell(cell);
     auto& J = fvcell.jacobian();
     EXPECT_EQ(J.size(), 11u);
diff --git a/tests/validation/validate_synapses.cpp b/tests/validation/validate_synapses.cpp
index 3dbf7fbb62efc44d128f58222b22f3f2ae437eaf..9bc67172879d14e8aea1aed21311c344fcb9f64a 100644
--- a/tests/validation/validate_synapses.cpp
+++ b/tests/validation/validate_synapses.cpp
@@ -75,7 +75,7 @@ void run_neuron_baseline(const char* syn_type, const char* data_file)
     auto probe_dend = cell.add_probe({{1,0.5}, probeKind::membrane_voltage});
 
     // injected spike events
-    postsynaptic_spike_event synthetic_events[] = {
+    postsynaptic_spike_event<float> synthetic_events[] = {
         {{0u, 0u}, 10.0, 0.04},
         {{0u, 0u}, 20.0, 0.04},
         {{0u, 0u}, 40.0, 0.04}