diff --git a/src/fvm_multicell.hpp b/src/fvm_multicell.hpp
index ba2cb5c3c6a0d74070b81eb823dd3d1544cf4ce4..b952d80765dc8f4c6dc6474c77a2557444f1509b 100644
--- a/src/fvm_multicell.hpp
+++ b/src/fvm_multicell.hpp
@@ -18,7 +18,6 @@
 #include <profiling/profiler.hpp>
 #include <segment.hpp>
 #include <stimulus.hpp>
-#include <util/debug.hpp>
 #include <util/meta.hpp>
 #include <util/partition.hpp>
 #include <util/rangeutil.hpp>
@@ -501,16 +500,20 @@ void fvm_multicell<Backend>::initialize(
     current_ = array(ncomp, 0);
     voltage_ = array(ncomp, resting_potential_);
 
-    // create maps for mechanism initialization.
+    // look up table: (density) mechanism name -> list of CV range objects
     std::map<std::string, std::vector<segment_cv_range>> mech_map;
-    std::vector<std::vector<cell_lid_type>> syn_mech_map;
-    std::map<std::string, std::size_t> syn_mech_indices;
+
+    // look up table: point mechanism (synapse) name -> CV indices and target numbers.
+    struct syn_cv_and_target {
+        cell_lid_type cv;
+        cell_lid_type target;
+    };
+    std::map<std::string, std::vector<syn_cv_and_target>> syn_mech_map;
 
     // initialize vector used for matrix creation.
     std::vector<size_type> group_parent_index(ncomp);
 
     // create each cell:
-    auto target_hi = target_handles.begin();
     auto probe_hi = probe_handles.begin();
 
     // Allocate scratch storage for calculating quantities used to build the
@@ -573,20 +576,12 @@ void fvm_multicell<Backend>::initialize(
             EXPECTS(targets_count < targets_size);
 
             const auto& name = syn.mechanism.name();
-            std::size_t syn_mech_index = 0;
-            if (syn_mech_indices.count(name)==0) {
-                syn_mech_index = syn_mech_map.size();
-                syn_mech_indices[name] = syn_mech_index;
-                syn_mech_map.push_back({});
-            }
-            else {
-                syn_mech_index = syn_mech_indices[name];
-            }
+            auto& map_entry = syn_mech_map[name];
 
-            auto& map_entry = syn_mech_map[syn_mech_index];
+            cell_lid_type syn_cv = comp_ival.first + find_cv_index(syn.location, graph);
+            cell_lid_type target_index = targets_count++;
 
-            auto syn_cv = comp_ival.first + find_cv_index(syn.location, graph);
-            map_entry.push_back(syn_cv);
+            map_entry.push_back(syn_cv_and_target{syn_cv, target_index});
         }
 
         //
@@ -703,36 +698,24 @@ void fvm_multicell<Backend>::initialize(
         }
 
         mechanisms_.push_back(
-            backend::make_mechanism(mech.first, voltage_, current_, mech_cv_weight, mech_cv_index)
-        );
+            backend::make_mechanism(mech.first, voltage_, current_, mech_cv_weight, mech_cv_index));
 
-        // save the indices for easy lookup later in initialization
+        // Save the indices for ion set up below.
         mech_index_map[mech.first] = mech_cv_index;
     }
 
-    // Create point (synapse) mechanisms
-    for (const auto& syni: syn_mech_indices) {
-        const auto& mech_name = syni.first;
+    // Create point (synapse) mechanisms.
+    for (auto& syni: syn_mech_map) {
         size_type mech_index = mechanisms_.size();
 
-        auto cv_map = syn_mech_map[syni.second];
-        size_type n_indices = size(cv_map);
-
-        // sort indices but keep track of their original order for assigning
-        // target handles
-        using index_pair = std::pair<cell_lid_type, size_type>;
-        auto cv_index = [](index_pair x) { return x.first; };
-        auto target_index = [](index_pair x) { return x.second; };
-
-        std::vector<index_pair> permute;
-        assign_by(permute, make_span(0u, n_indices),
-            [&](size_type i) { return index_pair(cv_map[i], i); });
+        const auto& mech_name = syni.first;
+        auto& cv_assoc = syni.second;
 
-        // sort the cv information in order of cv index
-        sort_by(permute, cv_index);
 
-        std::vector<cell_lid_type> cv_indices =
-            assign_from(transform_view(permute, cv_index));
+        // Sort CV indices but keep track of their corresponding targets.
+        auto cv_index = [](syn_cv_and_target x) { return x.cv; };
+        util::sort_by(cv_assoc, cv_index);
+        std::vector<cell_lid_type> cv_indices = assign_from(transform_view(cv_assoc, cv_index));
 
         // Create the mechanism.
         // An empty weight vector is supplied, because there are no weights applied to point
@@ -740,16 +723,14 @@ void fvm_multicell<Backend>::initialize(
         mechanisms_.push_back(
             backend::make_mechanism(mech_name, voltage_, current_, {}, cv_indices));
 
-        // save the compartment indexes for this synapse type
+        // Save the indices for ion set up below.
         mech_index_map[mech_name] = cv_indices;
 
-        // make target handles
-        std::vector<target_handle> handles(n_indices);
-        for (auto i: make_span(0u, n_indices)) {
-            handles[target_index(permute[i])] = {mech_index, i};
+        // Make the target handles.
+        cell_lid_type instance = 0;
+        for (auto entry: cv_assoc) {
+            target_handles[entry.target] = {mech_index, instance++};
         }
-        target_hi = std::copy_n(std::begin(handles), n_indices, target_hi);
-        targets_count += n_indices;
     }
 
     // confirm user-supplied containers for targets are appropriately sized
diff --git a/tests/unit/test_fvm_multi.cpp b/tests/unit/test_fvm_multi.cpp
index 68d25afa43d30b50b2b018904e4e327691695870..7f491f9fb7d7b748e3743b081a5351bf4dbe364b 100644
--- a/tests/unit/test_fvm_multi.cpp
+++ b/tests/unit/test_fvm_multi.cpp
@@ -396,29 +396,33 @@ void run_target_handle_test(std::vector<handle_info> all_handles) {
 
 TEST(fvm_multi, target_handles_onecell)
 {
-    SCOPED_TRACE("handles: exp2syn only on cell 0");
-    std::vector<handle_info> handles0 = {
-        {0, "exp2syn",  4},
-        {0, "exp2syn",  4},
-        {0, "exp2syn",  3},
-        {0, "exp2syn",  2},
-        {0, "exp2syn",  0},
-        {0, "exp2syn",  1},
-        {0, "exp2syn",  2}
-    };
-    run_target_handle_test(handles0);
+    {
+        SCOPED_TRACE("handles: exp2syn only on cell 0");
+        std::vector<handle_info> handles0 = {
+            {0, "exp2syn",  4},
+            {0, "exp2syn",  4},
+            {0, "exp2syn",  3},
+            {0, "exp2syn",  2},
+            {0, "exp2syn",  0},
+            {0, "exp2syn",  1},
+            {0, "exp2syn",  2}
+        };
+        run_target_handle_test(handles0);
+    }
 
-    SCOPED_TRACE("handles: expsyn only on cell 1");
-    std::vector<handle_info> handles1 = {
-        {1, "expsyn",  4},
-        {1, "expsyn",  4},
-        {1, "expsyn",  3},
-        {1, "expsyn",  2},
-        {1, "expsyn",  0},
-        {1, "expsyn",  1},
-        {1, "expsyn",  2}
-    };
-    run_target_handle_test(handles1);
+    {
+        SCOPED_TRACE("handles: expsyn only on cell 1");
+        std::vector<handle_info> handles1 = {
+            {1, "expsyn",  4},
+            {1, "expsyn",  4},
+            {1, "expsyn",  3},
+            {1, "expsyn",  2},
+            {1, "expsyn",  0},
+            {1, "expsyn",  1},
+            {1, "expsyn",  2}
+        };
+        run_target_handle_test(handles1);
+    }
 }
 
 TEST(fvm_multi, target_handles_twocell)