diff --git a/src/cell.cpp b/src/cell.cpp
index a124eb384837e35215823bc8812f399905f56b68..ab01007a206ea241befea21fbed83c531298a36d 100644
--- a/src/cell.cpp
+++ b/src/cell.cpp
@@ -9,7 +9,6 @@ cell::cell()
// insert a placeholder segment for the soma
segments_.push_back(make_segment<placeholder_segment>());
parents_.push_back(0);
- stale_ = true;
}
int cell::num_segments() const
@@ -36,7 +35,6 @@ void cell::add_soma(value_type radius, point_type center)
else {
segments_[0] = make_segment<soma_segment>(radius);
}
- stale_ = true;
}
void cell::add_cable(cell::index_type parent, segment_ptr&& cable)
@@ -56,7 +54,6 @@ void cell::add_cable(cell::index_type parent, segment_ptr&& cable)
}
segments_.push_back(std::move(cable));
parents_.push_back(parent);
- stale_ = true;
}
segment* cell::segment(int index)
@@ -87,21 +84,14 @@ bool cell::has_soma() const
soma_segment* cell::soma()
{
- stale_ = true;
if(has_soma()) {
return segment(0)->as_soma();
}
return nullptr;
}
-// this breaks the use of stale_, because the user could modify a cable obtained from
-// this call, without the stale_ tag being set.
-//
-// set stale_ to true, then expect the user to make any modifications before calling
-// graph() etc.
cable_segment* cell::cable(int index)
{
- stale_ = true;
if(index>0 && index<num_segments()) {
return segment(index)->as_cable();
}
@@ -145,38 +135,27 @@ std::vector<int> cell::compartment_counts() const
comp_count.push_back(s->num_compartments());
}
return comp_count;
-
}
-void cell::construct() const
+int cell::num_compartments() const
{
- std::lock_guard<std::mutex> lock(mutex_);
-
- if(stale_) {
- tree_ = cell_tree(parents_);
- auto counts = compartment_counts();
- parent_index_ = make_parent_index(tree_.graph(), counts);
- segment_index_ = algorithms::make_index(counts);
+ auto n = 0;
+ for(auto &s : segments_) {
+ n += s->num_compartments();
}
- stale_ = false;
+ return n;
}
-std::vector<int> const& cell::parent_index() const
+compartment_model cell::model() const
{
- construct();
- return parent_index_;
-}
+ compartment_model m;
-std::vector<int> const& cell::segment_index() const
-{
- construct();
- return segment_index_;
-}
+ m.tree = cell_tree(parents_);
+ auto counts = compartment_counts();
+ m.parent_index = make_parent_index(m.tree.graph(), counts);
+ m.segment_index = algorithms::make_index(counts);
-cell_tree const& cell::tree() const
-{
- construct();
- return tree_;
+ return m;
}
std::vector<int> const& cell::segment_parents() const
diff --git a/src/cell.hpp b/src/cell.hpp
index 0a254e1ec006dec417b89ef36fa8f28631a283b7..68bc4c5a21f99237b18557f690226c0441e580c6 100644
--- a/src/cell.hpp
+++ b/src/cell.hpp
@@ -11,7 +11,15 @@
namespace nest {
namespace mc {
-// high-level abstract representation of a cell and its segments
+/// wrapper around compartment layout information derived from a high level cell
+/// description
+struct compartment_model {
+ cell_tree tree;
+ std::vector<int> parent_index;
+ std::vector<int> segment_index;
+};
+
+/// high-level abstract representation of a cell and its segments
class cell {
public:
@@ -61,10 +69,10 @@ class cell {
/// the surface area of the cell
value_type area() const;
- std::vector<segment_ptr> const& segments() const;
+ /// the total number of compartments over all segments
+ int num_compartments() const;
- /// the connectivity graph for the cell segments
- cell_tree const& tree() const;
+ std::vector<segment_ptr> const& segments() const;
/// return reference to array that enumerates the index of the parent of
/// each segment
@@ -73,46 +81,14 @@ class cell {
/// return a vector with the compartment count for each segment in the cell
std::vector<int> compartment_counts() const;
- /// return the parent index for the compartments
- std::vector<int> const& parent_index() const;
-
- /// Return the segment index for the compartments
- /// the segment index is an index into parent_index for looking
- /// up the set of compartments associated with a segment.
- /// i.e. the compartments for segment i are in the half open range
- /// [segment_index()[i], segmend_index()[i+1])
- std::vector<int> const& segment_index() const;
+ compartment_model model() const;
private:
- /// generate the internal representation of the connectivity
- /// graph for the cell segments
- void construct() const;
-
- //
- // the local description of the cell which can be modified by the user
- // in a ad-hoc manner (adding segments, modifying segments, etc)
- //
-
// storage for connections
std::vector<index_type> parents_;
// the segments
std::vector<segment_ptr> segments_;
-
- // used internally to mark whether derived data (tree_, parent_index_, etc)
- // are out of date
- mutable bool stale_ = true;
-
- //
- // fixed cell description, which is computed from the layout description
- // this computed whenever a call to the graph() method is made
- // the graph method is const, so tree_ is mutable
- //
-
- mutable std::mutex mutex_;
- mutable cell_tree tree_;
- mutable std::vector<int> parent_index_;
- mutable std::vector<int> segment_index_;
};
// create a cable by forwarding cable construction parameters provided by the user
@@ -125,7 +101,6 @@ void cell::add_cable(cell::index_type parent, Args ...args)
"parent index of cell segment is out of range"
);
}
- stale_ = true;
segments_.push_back(make_segment<cable_segment>(std::forward<Args>(args)...));
parents_.push_back(parent);
}
diff --git a/src/fvm.hpp b/src/fvm.hpp
index 9e84119f526c531f3e80c082ea22d8dc7edd997b..1cab7b19e0ded99986648f2a0759e716b1112b2e 100644
--- a/src/fvm.hpp
+++ b/src/fvm.hpp
@@ -97,18 +97,19 @@ class fvm_cell {
template <typename T, typename I>
fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell)
-: matrix_ {cell.parent_index()}
-, cv_areas_ {size(), T(0)}
-, face_alpha_ {size(), T(0)}
-, cv_capacitance_{size(), T(0)}
-, current_ {size(), T(0)}
-, voltage_ {size(), T(0)}
+: cv_areas_ {cell.num_compartments(), T(0)}
+, face_alpha_ {cell.num_compartments(), T(0)}
+, cv_capacitance_{cell.num_compartments(), T(0)}
+, current_ {cell.num_compartments(), T(0)}
+, voltage_ {cell.num_compartments(), T(0)}
{
using util::left;
using util::right;
+ const auto graph = cell.model();
+ matrix_ = matrix_type(graph.parent_index);
auto parent_index = matrix_.p();
- auto const& segment_index = cell.segment_index();
+ auto const& segment_index = graph.segment_index;
auto seg_idx = 0;
for(auto const& s : cell.segments()) {
diff --git a/src/matrix.hpp b/src/matrix.hpp
index 3e5f4442373c24821bc9f6b8499db90a37a87835..16936fa47c26d3c632d08d008e59c76c2e4b0db0 100644
--- a/src/matrix.hpp
+++ b/src/matrix.hpp
@@ -24,6 +24,8 @@ class matrix {
using index_type = memory::HostVector<size_type>;
using index_view = typename index_type::view_type;
+ matrix() = default;
+
/// construct matrix for one or more cells, with combined parent index
/// and a cell index
template <
diff --git a/tests/test_cell.cpp b/tests/test_cell.cpp
index 09342b86e8d95a3185af68a903a7f59abdf77f2a..88c8dcaced167d4030529adb8a348a116158c17f 100644
--- a/tests/test_cell.cpp
+++ b/tests/test_cell.cpp
@@ -145,7 +145,8 @@ TEST(cell_type, multiple_cables)
EXPECT_EQ(c.area(), 8. + math::area_sphere(soma_radius));
// construct the graph
- auto const& con = c.tree();
+ const auto model = c.model();
+ auto const& con = model.tree;
EXPECT_EQ(con.num_segments(), 5u);
EXPECT_EQ(con.parent(0), -1);
diff --git a/tests/test_run.cpp b/tests/test_run.cpp
index 712fca4346e2a1780a9c1c3dca080381eeb8218d..c4e3b1025e82ca257295fdcf8980fd82240d1956 100644
--- a/tests/test_run.cpp
+++ b/tests/test_run.cpp
@@ -15,7 +15,7 @@ TEST(run, cable)
cell.add_cable(0, segmentKind::dendrite, 1e-4, 1e-4, 4e-1);
std::cout << cell.segment(1)->area() << " is the area\n";
- EXPECT_EQ(cell.tree().num_segments(), 2u);
+ EXPECT_EQ(cell.model().tree.num_segments(), 2u);
cell.soma()->add_mechanism(hh_parameters());
@@ -49,8 +49,6 @@ TEST(run, cable)
J.rhs()[0] = 10.;
J.solve();
-
- //std::cout << "x" << J.rhs() << "\n";
}
TEST(run, init)
@@ -64,7 +62,8 @@ TEST(run, init)
cell.add_cable(0, segmentKind::dendrite, 0.5, 0.5, 200);
- EXPECT_EQ(cell.tree().num_segments(), 2u);
+ const auto m = cell.model();
+ EXPECT_EQ(m.tree.num_segments(), 2u);
// in this context (i.e. attached to a segment on a high-level cell)
// a mechanism is essentially a set of parameters