From 6c8bd39aad9dd27117f460b7346261637b277314 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 13 Sep 2023 14:15:49 +0200 Subject: [PATCH 1/7] Null check in `operator<<(std::ostream, Node)`. (#2496) --- src/neuron/container/node.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/neuron/container/node.hpp b/src/neuron/container/node.hpp index cfa6105958..b477c70d3f 100644 --- a/src/neuron/container/node.hpp +++ b/src/neuron/container/node.hpp @@ -244,9 +244,13 @@ struct handle_interface: handle_base { } friend std::ostream& operator<<(std::ostream& os, handle_interface const& handle) { - return os << "Node{" << handle.id() << '/' << handle.underlying_storage().size() - << " v=" << handle.v() << " area=" << handle.area() << " a=" << handle.a() - << " b=" << handle.b() << " d=" << handle.d() << '}'; + if (handle.id()) { + return os << "Node{" << handle.id() << '/' << handle.underlying_storage().size() + << " v=" << handle.v() << " area=" << handle.area() << " a=" << handle.a() + << " b=" << handle.b() << " d=" << handle.d() << '}'; + } else { + os << "Node{null}"; + } } }; } // namespace neuron::container::Node From 3c9582156848048937dba9caf02d0ff82ecb433b Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 13 Sep 2023 14:16:11 +0200 Subject: [PATCH 2/7] Update coding-conventions to use `copy_if_different`. (#2500) --- external/coding-conventions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/coding-conventions b/external/coding-conventions index a37793313e..3d157f9c8e 160000 --- a/external/coding-conventions +++ b/external/coding-conventions @@ -1 +1 @@ -Subproject commit a37793313ebd9a69cd96e4cf6d3183fa51b81c33 +Subproject commit 3d157f9c8ea94d196a825aaa7f523265e360dc4b From 047d8f1bce6f9dfefe16c20c3c72e763a45ce168 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 13 Sep 2023 14:16:30 +0200 Subject: [PATCH 3/7] Add more REQUIRE empty checks. (#2498) Since we need to test via a global, bugs from prior tests may affect later tests. One variant is that if there's a bug in releasing rows, the model wont be in the expected (empty) state and fail on an unrelated test. This commit adds a few more checks to make sure it's in the expected state. --- test/unit_tests/container/node.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit_tests/container/node.cpp b/test/unit_tests/container/node.cpp index 7d32c71ad5..0825f0bc5f 100644 --- a/test/unit_tests/container/node.cpp +++ b/test/unit_tests/container/node.cpp @@ -258,6 +258,7 @@ std::tuple, std::vector> get_nodes_and_reference_vol } // namespace neuron::test TEST_CASE("SOA-backed Node structure", "[Neuron][data_structures][node]") { + REQUIRE(neuron::model().node_data().size() == 0); GIVEN("A default-constructed node") { ::Node node{}; THEN("Check its SOA-backed members have their default values") { @@ -443,9 +444,12 @@ TEST_CASE("SOA-backed Node structure", "[Neuron][data_structures][node]") { } } } + REQUIRE(neuron::model().node_data().size() == 0); } TEST_CASE("Fast membrane current storage", "[Neuron][data_structures][node][fast_imem]") { + REQUIRE(neuron::model().node_data().size() == 0); + auto const set_fast_imem = [](bool new_value) { nrn_use_fast_imem = new_value; nrn_fast_imem_alloc(); @@ -467,6 +471,7 @@ TEST_CASE("Fast membrane current storage", "[Neuron][data_structures][node][fast GIVEN("fast_imem calculation is disabled") { set_fast_imem(false); WHEN("A node is default-constructed") { + REQUIRE(neuron::model().node_data().size() == 0); ::Node node{}; check_throws(node); auto handle = node.sav_rhs_handle(); From 4f5e337676766c1361a8f8e592c135f2adfe5887 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 13 Sep 2023 18:38:28 +0200 Subject: [PATCH 4/7] Increase CI timeout limit to 75 minutes. (#2501) --- .github/workflows/neuron-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 3156f71d19..2fba4088ad 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -27,7 +27,7 @@ jobs: name: ${{ matrix.os }} - ${{ matrix.config.build_mode }} (${{ matrix.config.cmake_option }}${{ matrix.config.config_options }}${{ matrix.config.matrix_eval }}${{ matrix.config.sanitizer }}) - timeout-minutes: 45 + timeout-minutes: 75 env: INSTALL_DIR: install From 93c671b519b7f5a3c5d5397e48343a1d96cb1f91 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Thu, 14 Sep 2023 13:53:32 +0200 Subject: [PATCH 5/7] Improve freeing memory of soa containers (#2455) call `shrink_to_fit` for all vectors in the model during `pool_shrink`. --- src/neuron/container/soa_container.hpp | 10 ++++++++++ src/neuron/model_data.hpp | 7 +++++++ src/nrniv/cxprop.cpp | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/neuron/container/soa_container.hpp b/src/neuron/container/soa_container.hpp index 8f653d418c..08591c9b32 100644 --- a/src/neuron/container/soa_container.hpp +++ b/src/neuron/container/soa_container.hpp @@ -765,6 +765,16 @@ struct soa { return result; } + void shrink_to_fit() { + if (m_frozen_count) { + throw_error("shrink() called on a frozen structure"); + } + for_each_vector( + [](auto const& tag, auto& vec, int field_index, int array_dim) { + vec.shrink_to_fit(); + }); + } + private: /** * @brief Remove the @f$i^{\text{th}}@f$ row from the container. diff --git a/src/neuron/model_data.hpp b/src/neuron/model_data.hpp index 1f7b9e55b4..e8eb336e2a 100644 --- a/src/neuron/model_data.hpp +++ b/src/neuron/model_data.hpp @@ -117,6 +117,13 @@ struct Model { [[nodiscard]] std::unique_ptr find_container_info( void const* cont) const; + void shrink_to_fit() { + m_node_data.shrink_to_fit(); + apply_to_mechanisms([](auto& mech_data) { mech_data.shrink_to_fit(); }); + + m_identifier_ptrs_for_deferred_deletion.shrink_to_fit(); + } + private: container::Mechanism::storage& mechanism_data_impl(int type) const { if (0 <= type && type >= m_mech_data.size()) { diff --git a/src/nrniv/cxprop.cpp b/src/nrniv/cxprop.cpp index ee7e3f1d71..08921d655b 100644 --- a/src/nrniv/cxprop.cpp +++ b/src/nrniv/cxprop.cpp @@ -2,6 +2,7 @@ #include "hocdec.h" // Datum #include "section.h" // Section #include "structpool.h" // Pool +#include "../neuron/model_data.hpp" #include #include @@ -111,6 +112,7 @@ void nrn_poolshrink(int shrink) { pdatum.reset(); } } + neuron::model().shrink_to_fit(); } else { Printf("poolshrink --- type name (dbluse, size) (datumuse, size)\n"); for (auto i = 0; i < datumpools().size(); ++i) { From e742cdfc4b079c4c9a92d8c00def2bab367ed4d6 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Thu, 14 Sep 2023 16:29:41 +0200 Subject: [PATCH 6/7] Remove `non_owning_*::get_raw_pointer()`. (#2497) --- src/neuron/container/non_owning_soa_identifier.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/neuron/container/non_owning_soa_identifier.hpp b/src/neuron/container/non_owning_soa_identifier.hpp index 5361dccfb7..fc3a5e9cd7 100644 --- a/src/neuron/container/non_owning_soa_identifier.hpp +++ b/src/neuron/container/non_owning_soa_identifier.hpp @@ -69,13 +69,6 @@ struct non_owning_identifier_without_container { return !m_ptr; } - /** - * @brief Get the underlying pointer value. - */ - [[nodiscard]] std::size_t* get_raw_pointer() const { - return m_ptr; - } - friend std::ostream& operator<<(std::ostream& os, non_owning_identifier_without_container const& id) { if (!id.m_ptr) { From adec04554aca573151679e5b3908c458c5e6adb3 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 18 Sep 2023 03:30:34 -0400 Subject: [PATCH 7/7] Fixed mnod file array variable assignment (seg.mech.array[i] = x) (#2504) --- src/nrnpython/nrnpy_nrn.cpp | 4 +--- test/hoctests/vardimtests/test2.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/nrnpython/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 156fa8d0a8..1563b6bb2d 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -2223,8 +2223,7 @@ static int rv_setitem(PyObject* self, Py_ssize_t ix, PyObject* value) { return -1; } int err; - // Bug that ix is not passed as the last argument? - auto const d = nrnpy_rangepointer(sec, r->sym_, r->pymech_->pyseg_->x_, &err, 0 /* idx */); + auto const d = nrnpy_rangepointer(sec, r->sym_, r->pymech_->pyseg_->x_, &err, ix); if (!d) { rv_noexist(sec, r->sym_->name, r->pymech_->pyseg_->x_, err); return -1; @@ -2244,7 +2243,6 @@ static int rv_setitem(PyObject* self, Py_ssize_t ix, PyObject* value) { neuron::container::data_handle{neuron::container::do_not_search, &x}, 0); } else { - assert(ix == 0); // d += ix; if (!PyArg_Parse(value, "d", static_cast(d))) { PyErr_SetString(PyExc_ValueError, "bad value"); return -1; diff --git a/test/hoctests/vardimtests/test2.py b/test/hoctests/vardimtests/test2.py index 0f20505b9e..7801faa702 100644 --- a/test/hoctests/vardimtests/test2.py +++ b/test/hoctests/vardimtests/test2.py @@ -34,3 +34,30 @@ h("""objref oarray[4][4]""") # cannot reach line we want because of earlier array check expect_err("h.oarray[2] = []") + + +# test assignment/evaluation of mod file array variable from python +s = h.Section() +s.nseg = 3 +s.insert("atst") +for seg in s: + ar = seg.atst.arrayrng + assert len(ar) == 4 + for i in range(len(ar)): + ar[i] = i + seg.x + seg.arrayrng_atst[i] = ar[i] +for seg in s: + ar = seg.atst.arrayrng + for i in range(len(ar)): + assert ar[i] == i + seg.x + assert seg.arrayrng_atst[i] == i + seg.x + +ar = s.arrayrng_atst +assert len(ar) == 4 +for i in range(len(ar)): + ar[i] = i +for i in range(len(ar)): + assert ar[i] == float(i) + +expect_err("print(ar[10])") +expect_err("ar[10] = 1")