From 717499a3501ae5aaee5ead294b3409eeff05a5f6 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Tue, 19 Mar 2024 21:23:17 +0100 Subject: [PATCH 01/62] Workaround for sanitizer issue in GA CI (#2788) --- .github/workflows/neuron-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index b8610c80c6..e39caea04f 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -89,6 +89,14 @@ jobs: fail-fast: false steps: + + - name: Fix kernel mmap rnd bits + # Asan in llvm 14 provided in ubuntu 22.04 is incompatible with + # high-entropy ASLR in much newer kernels that GitHub runners are + # using leading to random crashes: https://reviews.llvm.org/D148280 + run: sudo sysctl vm.mmap_rnd_bits=28 + if: matrix.os == 'ubuntu-22.04' + - name: Setup cmake uses: jwlawson/actions-setup-cmake@v2 with: From 222448490624825a1fc024f63cbc76aa2fb4f882 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 21 Mar 2024 04:08:50 +0700 Subject: [PATCH 02/62] Remove useless files dbrowser.h (#2789) --- src/ivoc/dbrowser.h | 62 --------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 src/ivoc/dbrowser.h diff --git a/src/ivoc/dbrowser.h b/src/ivoc/dbrowser.h deleted file mode 100644 index 45682ab754..0000000000 --- a/src/ivoc/dbrowser.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1991 Stanford University - * Copyright (c) 1991 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Stanford and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Stanford and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* - * DocBrowser -- browse a directory - */ - -#ifndef dbrowser_h -#define dbrowser_h - -#include - -class Adjustable; -class DocBrowserImpl; -class WidgetKit; -class Word; - -class DocBrowser: public Browser { - public: - DocBrowser(TBScrollBox*, WidgetKit*); - virtual ~DocBrowser(); - - virtual void press(const Event&); - virtual void drag(const Event&); - virtual void release(const Event&); - virtual void keystroke(const Event&); - virtual InputHandler* focus_in(); - virtual void focus_out(); - - virtual void select(GlyphIndex); - - virtual Adjustable* adjustable() const; - virtual void refresh(); - virtual void select_word_action(Action*); - virtual Word* select_word(); - - private: - DocBrowserImpl* impl_; -}; - -#endif From 4035925b1012368ecb3e8d27040d717e0532ca80 Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Fri, 22 Mar 2024 14:02:19 +0100 Subject: [PATCH 03/62] Increase memory available for Gitlab CI jobs on BB5 (#2793) --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa9dc5cf0e..d06798d067 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -167,7 +167,7 @@ simulation_stack: variables: bb5_ntasks: 2 # so we block 16 cores bb5_cpus_per_task: 8 # ninja -j {this} - bb5_memory: 76G # ~16*384/80 + bb5_memory: 120G # ~1.5*16*384/80 (~1.5x more as we have seen OOMs) .spack_intel: variables: @@ -192,7 +192,7 @@ simulation_stack: extends: [.ctest] variables: bb5_ntasks: 16 - bb5_memory: 76G # ~16*384/80 + bb5_memory: 120G # ~1.5*16*384/80 (~1.5x more as we have seen OOMs) # Build NMODL once with GCC build:nmodl: From 858895287dfa8780f98b05dd3090bf6af3949ca4 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Sat, 23 Mar 2024 00:42:30 +0700 Subject: [PATCH 04/62] Use only pragma once (#2784) * Use only pragma once * Fix formatting * Revert for weird ivos * more ivos * pragma once for gnu too * revert one --------- Co-authored-by: Nicolas Cornu Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/gnu/ACG.h | 5 +---- src/gnu/Binomial.h | 8 +------- src/gnu/DiscUnif.h | 8 +------- src/gnu/Erlang.h | 8 +------- src/gnu/Geom.h | 10 +--------- src/gnu/HypGeom.h | 8 +------- src/gnu/LogNorm.h | 8 +------- src/gnu/MLCG.h | 8 +------- src/gnu/NegExp.h | 8 +------- src/gnu/Normal.h | 9 +-------- src/gnu/Poisson.h | 9 +-------- src/gnu/RNG.h | 10 +--------- src/gnu/Random.h | 8 +------- src/gnu/RndInt.h | 9 +-------- src/gnu/Uniform.h | 8 +------- src/gnu/Weibull.h | 8 +------- src/gnu/neuron_gnu_std.h | 4 +--- src/gnu/nrnran123.h | 5 +---- src/ivoc/apwindow.h | 5 +---- src/ivoc/axis.h | 5 +---- src/ivoc/bndedval.h | 6 +----- src/ivoc/cbwidget.h | 5 +---- src/ivoc/checkpnt.h | 5 +---- src/ivoc/epsprint.h | 5 +---- src/ivoc/field.h | 5 +---- src/ivoc/fourier.h | 4 +--- src/ivoc/graph.h | 5 +---- src/ivoc/grglyph.h | 5 +---- src/ivoc/hocmark.h | 5 +---- src/ivoc/htlist.h | 4 +--- src/ivoc/idraw.h | 6 +----- src/ivoc/ivoc.h | 5 +---- src/ivoc/ivocconf.h | 5 +---- src/ivoc/ivocvect.h | 5 +---- src/ivoc/mymath.h | 5 +---- src/ivoc/nrngsl.h | 4 +--- src/ivoc/nrnsymdiritem.h | 5 +---- src/ivoc/objcmd.h | 5 +---- src/ivoc/oc2iv.h | 5 +---- src/ivoc/ocbox.h | 5 +---- src/ivoc/ocbrowsr.h | 5 +---- src/ivoc/ocdeck.h | 5 +---- src/ivoc/ocfile.h | 5 +---- src/ivoc/ocglyph.h | 5 +---- src/ivoc/oclist.h | 5 +---- src/ivoc/ocmatrix.h | 5 +---- src/ivoc/ocobserv.h | 5 +---- src/ivoc/ocpicker.h | 4 +--- src/ivoc/ocpointer.h | 5 +---- src/ivoc/rect.h | 5 +---- src/ivoc/rubband.h | 5 +---- src/ivoc/scenepic.h | 5 +---- src/ivoc/scenevie.h | 6 +----- src/ivoc/symchoos.h | 5 +---- src/ivoc/symdir.h | 5 +---- src/ivoc/utility.h | 5 +---- src/ivoc/xmenu.h | 6 +----- src/ivos/InterViews/coord.h | 5 +---- src/ivos/InterViews/enter-scope.h | 5 +---- src/ivos/InterViews/geometry.h | 5 +---- src/ivos/InterViews/iv.h | 5 +---- src/ivos/InterViews/observe.h | 5 +---- src/ivos/InterViews/resource.h | 5 +---- src/ivos/OS/os.h | 5 +---- src/nrncvode/cvodeobj.h | 5 +---- src/nrncvode/netcon.h | 5 +---- src/nrncvode/netcvode.h | 5 +---- src/nrncvode/nrndaspk.h | 4 +--- src/nrncvode/pool.hpp | 6 +----- src/nrncvode/vrecitem.h | 5 +---- src/nrniv/bbsavestate.h | 5 +---- src/nrniv/glinerec.h | 5 +---- src/nrniv/kschan.h | 5 +---- src/nrniv/kssingle.h | 5 +---- src/nrniv/linmod.h | 5 +---- src/nrniv/matrixmap.h | 5 +---- src/nrniv/multisplitcontrol.h | 5 +---- src/nrniv/ndatclas.h | 5 +---- src/nrniv/nonlinz.h | 5 +---- src/nrniv/nrncore_write.h | 6 +----- src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h | 5 +---- src/nrniv/nrncore_write/data/cell_group.h | 5 +---- src/nrniv/nrncore_write/data/datum_indices.h | 5 +---- src/nrniv/nrncore_write/io/nrncore_io.h | 6 +----- src/nrniv/nrndae.h | 5 +---- src/nrniv/nrnmenu.h | 5 +---- src/nrniv/nrnoc2iv.h | 5 +---- src/nrniv/nrnsection_mapping.h | 5 +---- src/nrniv/nvector_nrnparallel_ld.h | 7 +------ src/nrniv/nvector_nrnserial_ld.h | 7 +------ src/nrniv/nvector_nrnthread.h | 7 +------ src/nrniv/nvector_nrnthread_ld.h | 7 +------ src/nrniv/ppshape.h | 5 +---- src/nrniv/rot3band.h | 5 +---- src/nrniv/rotate3d.h | 4 +--- src/nrniv/secbrows.h | 5 +---- src/nrniv/shape.h | 5 +---- src/nrniv/shapeplt.h | 5 +---- src/nrniv/structpool.h | 5 +---- src/nrnmpi/mpispike.h | 6 +----- src/nrnmpi/nrnmpidec.h | 5 +---- src/nrnoc/cabvars.h | 5 +---- src/nrnoc/gui-redirect.h | 5 +---- src/nrnoc/md1redef.h | 5 +---- src/nrnoc/md2redef.h | 5 +---- src/nrnoc/nonvintblock.h | 6 +----- src/nrnoc/nrniv_mf.h | 5 +---- src/nrnoc/nrnredef.h | 5 +---- src/nrnpython/hoccontext.h | 5 +---- src/nrnpython/nrnpy_utils.h | 5 +---- src/nrnpython/nrnpython.h | 4 +--- src/oc/classreg.h | 6 +----- src/oc/code.h | 6 +----- src/oc/hoc.h | 5 +---- src/oc/hoc_membf.h | 5 +---- src/oc/hocdec.h | 7 +------ src/oc/hocgetsym.h | 5 +---- src/oc/hoclist.h | 6 +----- src/oc/hocparse.h | 6 +----- src/oc/hocstr.h | 6 +----- src/oc/nrnapi.h | 5 +---- src/oc/nrnassrt.h | 6 +----- src/oc/nrnmpi.h | 4 +--- src/oc/nrnunits.h | 5 +---- src/oc/nrnwrap_dlfcn.h | 5 +---- src/oc/ocmisc.h | 5 +---- src/oc/profile.h | 5 +---- src/oc/redef.h | 5 +---- src/parallel/bbs.h | 5 +---- src/parallel/bbsdirect.h | 5 +---- src/parallel/bbsimpl.h | 5 +---- src/parallel/bbslocal.h | 5 +---- src/parallel/bbslsrv.h | 5 +---- src/parallel/bbslsrv2.h | 5 +---- src/parallel/bbsrcli.h | 5 +---- src/parallel/bbssrv.h | 4 +--- src/parallel/bbssrv2mpi.h | 5 +---- 137 files changed, 137 insertions(+), 615 deletions(-) diff --git a/src/gnu/ACG.h b/src/gnu/ACG.h index 63230e0031..e8fcd0eb5d 100755 --- a/src/gnu/ACG.h +++ b/src/gnu/ACG.h @@ -15,8 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _ACG_h -#define _ACG_h 1 +#pragma once #include "RNG.h" #include @@ -64,5 +63,3 @@ class ACG : public RNG { virtual uint32_t asLong(); virtual void reset(); }; - -#endif diff --git a/src/gnu/Binomial.h b/src/gnu/Binomial.h index f787477ed8..31923daf7a 100755 --- a/src/gnu/Binomial.h +++ b/src/gnu/Binomial.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Binomial_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Binomial_h 1 +#pragma once #include "Random.h" @@ -51,5 +47,3 @@ inline int Binomial::n(int xn) { int tmp = pN; pN = xn; return tmp; } inline double Binomial::u() { return pU; } inline double Binomial::u(int xu) { double tmp = pU; pU = xu; return tmp; } - -#endif diff --git a/src/gnu/DiscUnif.h b/src/gnu/DiscUnif.h index 9f1bafc63c..7214c9b13e 100755 --- a/src/gnu/DiscUnif.h +++ b/src/gnu/DiscUnif.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _DiscreteUniform_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _DiscreteUniform_h 1 +#pragma once #include "Random.h" @@ -68,5 +64,3 @@ inline long DiscreteUniform::high(long x) { delta = (pHigh - pLow) + 1; return tmp; } - -#endif diff --git a/src/gnu/Erlang.h b/src/gnu/Erlang.h index f000d3a568..98774310f0 100755 --- a/src/gnu/Erlang.h +++ b/src/gnu/Erlang.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Erlang_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Erlang_h 1 +#pragma once #include "Random.h" @@ -64,5 +60,3 @@ inline double Erlang::variance() { return pVariance; } inline double Erlang::variance(double x) { double tmp = pVariance; pVariance = x; setState(); return tmp; } - -#endif diff --git a/src/gnu/Geom.h b/src/gnu/Geom.h index 5f91085f51..cc0d8dcee6 100755 --- a/src/gnu/Geom.h +++ b/src/gnu/Geom.h @@ -15,12 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Geometric_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Geometric_h - +#pragma once #include "Random.h" class Geometric: public Random { @@ -47,6 +42,3 @@ inline double Geometric::mean() { return pMean; } inline double Geometric::mean(double x) { double tmp = pMean; pMean = x; return tmp; } - - -#endif diff --git a/src/gnu/HypGeom.h b/src/gnu/HypGeom.h index cc91112e4b..89278074c1 100755 --- a/src/gnu/HypGeom.h +++ b/src/gnu/HypGeom.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _HyperGeometric_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _HyperGeometric_h +#pragma once #include "Random.h" @@ -66,5 +62,3 @@ inline double HyperGeometric::variance(double x) { double t = pVariance; pVariance = x; setState(); return t; } - -#endif diff --git a/src/gnu/LogNorm.h b/src/gnu/LogNorm.h index 9218382617..5404c0e3f6 100755 --- a/src/gnu/LogNorm.h +++ b/src/gnu/LogNorm.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _LogNormal_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _LogNormal_h +#pragma once #include "Normal.h" @@ -74,5 +70,3 @@ inline double LogNormal::variance(double x) double t=logVariance; logVariance = x; setState(); return t; } - -#endif diff --git a/src/gnu/MLCG.h b/src/gnu/MLCG.h index 2b566acb91..eae70504a8 100755 --- a/src/gnu/MLCG.h +++ b/src/gnu/MLCG.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _MLCG_h -#define _MLCG_h 1 -#ifdef __GNUG__ -//#pragma interface -#endif +#pragma once #include "RNG.h" #include @@ -83,5 +79,3 @@ MLCG::reseed(int32_t s1, int32_t s2) initialSeedTwo = s2; reset(); } - -#endif diff --git a/src/gnu/NegExp.h b/src/gnu/NegExp.h index 1b8a48b032..57ef63d316 100755 --- a/src/gnu/NegExp.h +++ b/src/gnu/NegExp.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _NegativeExpntl_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _NegativeExpntl_h 1 +#pragma once // @@ -51,5 +47,3 @@ inline double NegativeExpntl::mean(double x) { double t = pMean; pMean = x; return t; } - -#endif diff --git a/src/gnu/Normal.h b/src/gnu/Normal.h index fbbc8716be..1f2bff87db 100755 --- a/src/gnu/Normal.h +++ b/src/gnu/Normal.h @@ -15,12 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Normal_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Normal_h - +#pragma once #include "Random.h" class Normal: public Random { @@ -62,5 +57,3 @@ inline double Normal::variance(double x) { pStdDev = sqrt(pVariance); return t; }; - -#endif diff --git a/src/gnu/Poisson.h b/src/gnu/Poisson.h index 4aad14d158..ba6497e481 100755 --- a/src/gnu/Poisson.h +++ b/src/gnu/Poisson.h @@ -15,12 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Poisson_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Poisson_h - +#pragma once #include "Random.h" class Poisson: public Random { @@ -47,5 +42,3 @@ inline double Poisson::mean(double x) { pMean = x; return t; } - -#endif diff --git a/src/gnu/RNG.h b/src/gnu/RNG.h index 578be4bd85..e7af070623 100755 --- a/src/gnu/RNG.h +++ b/src/gnu/RNG.h @@ -15,13 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _RNG_h -#define _RNG_h 1 -#ifdef __GNUG__ -//#pragma interface -#endif - - +#pragma once /* * int32_t and uint32_t have been defined by the configure procedure. Just * use these in place of the ones that libg++ used to provide. @@ -60,5 +54,3 @@ class RNG { virtual float asFloat(); virtual double asDouble(); }; - -#endif diff --git a/src/gnu/Random.h b/src/gnu/Random.h index fb6f7d067f..aae9a637ce 100755 --- a/src/gnu/Random.h +++ b/src/gnu/Random.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Random_h -#define _Random_h 1 -#ifdef __GNUG__ -//#pragma interface -#endif +#pragma once #include @@ -52,5 +48,3 @@ inline void Random::generator(RNG *p) { pGenerator = p; } - -#endif diff --git a/src/gnu/RndInt.h b/src/gnu/RndInt.h index c54b44de0e..3a46e9d9a5 100755 --- a/src/gnu/RndInt.h +++ b/src/gnu/RndInt.h @@ -30,12 +30,7 @@ License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _RandomInteger_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _RandomInteger_h 1 - +#pragma once // RandomInteger uses a random number generator to generate an integer // in a specified range. By default the range is 0..1. Since in my // experience random numbers are often needed for a wide variety of @@ -171,5 +166,3 @@ inline int RandomInteger:: asInt() { return int(asLong()); } - -#endif diff --git a/src/gnu/Uniform.h b/src/gnu/Uniform.h index b6a0016a09..e2f0d48d62 100755 --- a/src/gnu/Uniform.h +++ b/src/gnu/Uniform.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Uniform_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Uniform_h 1 +#pragma once #include "Random.h" @@ -67,5 +63,3 @@ inline double Uniform::high(double x) { delta = pHigh - pLow; return tmp; } - -#endif diff --git a/src/gnu/Weibull.h b/src/gnu/Weibull.h index 48ad831a56..6586b059f3 100755 --- a/src/gnu/Weibull.h +++ b/src/gnu/Weibull.h @@ -15,11 +15,7 @@ You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Weibull_h -#ifdef __GNUG__ -//#pragma interface -#endif -#define _Weibull_h +#pragma once #include "Random.h" @@ -70,5 +66,3 @@ inline double Weibull::beta(double x) { pBeta = x; return tmp; }; - -#endif diff --git a/src/gnu/neuron_gnu_std.h b/src/gnu/neuron_gnu_std.h index 059cef43cb..26ffb73449 100755 --- a/src/gnu/neuron_gnu_std.h +++ b/src/gnu/neuron_gnu_std.h @@ -17,8 +17,7 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _std_h -#define _std_h 1 +#pragma once #include #include #include @@ -28,4 +27,3 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include -#endif diff --git a/src/gnu/nrnran123.h b/src/gnu/nrnran123.h index e087a1607e..4777535f1c 100644 --- a/src/gnu/nrnran123.h +++ b/src/gnu/nrnran123.h @@ -1,5 +1,4 @@ -#ifndef nrnran123_h -#define nrnran123_h +#pragma once /* interface to Random123 */ /* http://www.thesalmons.org/john/random123/papers/random123sc11.pdf */ @@ -126,5 +125,3 @@ extern nrnran123_array4x32 nrnran123_iran3(std::uint32_t seq, std::uint32_t id1, std::uint32_t id2, std::uint32_t id3); - -#endif diff --git a/src/ivoc/apwindow.h b/src/ivoc/apwindow.h index 5c173056a0..c8083556be 100644 --- a/src/ivoc/apwindow.h +++ b/src/ivoc/apwindow.h @@ -1,5 +1,4 @@ -#ifndef dismiswin_h -#define dismiswin_h +#pragma once #include @@ -160,5 +159,3 @@ class PrintableWindowManager: public Observer { private: static PrintableWindowManager* current_; }; - -#endif diff --git a/src/ivoc/axis.h b/src/ivoc/axis.h index 3e6313b445..da65894ecf 100644 --- a/src/ivoc/axis.h +++ b/src/ivoc/axis.h @@ -1,5 +1,4 @@ -#ifndef axis_h -#define axis_h +#pragma once #include #include @@ -72,5 +71,3 @@ class AxisBackground: public Background { void draw_help(Canvas*, const Allocation&) const; void tic_label(Coord x, Coord y, Coord val, float x_align, float y_align, Canvas*) const; }; - -#endif diff --git a/src/ivoc/bndedval.h b/src/ivoc/bndedval.h index 219ae30517..f766f7e7e1 100644 --- a/src/ivoc/bndedval.h +++ b/src/ivoc/bndedval.h @@ -1,5 +1,4 @@ -#ifndef bounded_value_h -#define bounded_value_h +#pragma once #include @@ -37,6 +36,3 @@ class BoundedValue: public Adjustable { Coord scroll_incr_; Coord page_incr_; }; - - -#endif diff --git a/src/ivoc/cbwidget.h b/src/ivoc/cbwidget.h index c3dea0c488..74cd312dae 100644 --- a/src/ivoc/cbwidget.h +++ b/src/ivoc/cbwidget.h @@ -1,5 +1,4 @@ -#ifndef cbwidget_h -#define cbwidget_h +#pragma once #include class Graph; @@ -21,5 +20,3 @@ class ColorBrushWidget: public Action, public Observer { PolyGlyph* bb_; DismissableWindow* w_; }; - -#endif diff --git a/src/ivoc/checkpnt.h b/src/ivoc/checkpnt.h index 10b3580315..224e2d05e4 100644 --- a/src/ivoc/checkpnt.h +++ b/src/ivoc/checkpnt.h @@ -1,5 +1,4 @@ -#ifndef checkpoint_h -#define checkpoint_h +#pragma once #define CKPT(arg1, arg2) \ if (!arg1.xdr(arg2)) { \ @@ -17,5 +16,3 @@ class Checkpoint { bool xdr(long&); bool xdr(Object*&); }; - -#endif diff --git a/src/ivoc/epsprint.h b/src/ivoc/epsprint.h index a2bca59bcc..cc6664cf6f 100644 --- a/src/ivoc/epsprint.h +++ b/src/ivoc/epsprint.h @@ -1,5 +1,4 @@ -#ifndef epsprinter_h -#define epsprinter_h +#pragma once #include @@ -13,5 +12,3 @@ class EPSPrinter: public Printer { Coord height, const char* creator = "InterViews"); }; - -#endif diff --git a/src/ivoc/field.h b/src/ivoc/field.h index 214e6cc593..c90649674b 100644 --- a/src/ivoc/field.h +++ b/src/ivoc/field.h @@ -26,8 +26,7 @@ * FieldSEditor -- simple editor for text fields */ -#ifndef ivlook_sfield_h -#define ivlook_sfield_h +#pragma once #include #include @@ -126,5 +125,3 @@ class FieldSEditor: public InputHandler { private: FieldSEditorImpl* impl_; }; - -#endif diff --git a/src/ivoc/fourier.h b/src/ivoc/fourier.h index ae00699652..80989874a3 100644 --- a/src/ivoc/fourier.h +++ b/src/ivoc/fourier.h @@ -1,5 +1,4 @@ -#ifndef fourier_h -#define fourier_h +#pragma once void nrn_convlv(double* data, unsigned long n, @@ -13,4 +12,3 @@ void nrn_spctrm(double* data, double* psd, int setsize, int numsegpairs); void nrngsl_realft(double* data, unsigned long n, int isign); void nrn_gsl2nrc(double* gsl, double* nrc, unsigned long n); void nrn_nrc2gsl(double* nrc, double* gsl, unsigned long n); -#endif diff --git a/src/ivoc/graph.h b/src/ivoc/graph.h index 72e58b5874..65f5f3c174 100644 --- a/src/ivoc/graph.h +++ b/src/ivoc/graph.h @@ -1,5 +1,4 @@ -#ifndef graph_h -#define graph_h +#pragma once #include "neuron/container/data_handle.hpp" #include @@ -516,5 +515,3 @@ class BrushPalette { }; extern ColorPalette* colors; extern BrushPalette* brushes; - -#endif diff --git a/src/ivoc/grglyph.h b/src/ivoc/grglyph.h index ae322bd657..e5ad4fba45 100644 --- a/src/ivoc/grglyph.h +++ b/src/ivoc/grglyph.h @@ -1,5 +1,4 @@ -#ifndef grglyph_h -#define grglyph_h +#pragma once #include #include "graph.h" @@ -48,5 +47,3 @@ class GrGlyph: public Glyph { Object* obj_; Glyph* gif_; }; - -#endif diff --git a/src/ivoc/hocmark.h b/src/ivoc/hocmark.h index 65ad5ab0d7..ec5bf51e77 100644 --- a/src/ivoc/hocmark.h +++ b/src/ivoc/hocmark.h @@ -1,5 +1,4 @@ -#ifndef hocmark_h -#define hocmark_h +#pragma once #undef check @@ -37,5 +36,3 @@ class HocMark: public PolyGlyph { static PolyGlyph* mark_list_; static HocMark* most_recent_; }; - -#endif diff --git a/src/ivoc/htlist.h b/src/ivoc/htlist.h index 66e964893a..cab97c944f 100644 --- a/src/ivoc/htlist.h +++ b/src/ivoc/htlist.h @@ -29,8 +29,7 @@ for fast insertion, deletion, iteration * UList - list object. */ -#ifndef htlist_h -#define htlist_h +#pragma once class HTList { public: @@ -85,4 +84,3 @@ inline void* HTList::operator()() { inline void* HTList::vptr() { return _object; } -#endif diff --git a/src/ivoc/idraw.h b/src/ivoc/idraw.h index 64429a5751..9f20a12e32 100644 --- a/src/ivoc/idraw.h +++ b/src/ivoc/idraw.h @@ -1,5 +1,4 @@ -#ifndef ocidraw_h -#define ocidraw_h +#pragma once /* Hooks for special processing make use of the request() method in Glyphs. */ @@ -104,6 +103,3 @@ class OcIdraw { if (OcIdraw::idraw_stream) { \ OcIdraw::arg; \ } - - -#endif diff --git a/src/ivoc/ivoc.h b/src/ivoc/ivoc.h index c4875b634a..bb4cea1ffb 100644 --- a/src/ivoc/ivoc.h +++ b/src/ivoc/ivoc.h @@ -1,5 +1,4 @@ -#ifndef oc_h -#define oc_h +#pragma once #include #include @@ -85,5 +84,3 @@ class Oc { static Cursor* help_cursor_; static Observable* notify_change_; }; - -#endif diff --git a/src/ivoc/ivocconf.h b/src/ivoc/ivocconf.h index 0ffe854635..35f8b328fc 100644 --- a/src/ivoc/ivocconf.h +++ b/src/ivoc/ivocconf.h @@ -1,8 +1,5 @@ -#ifndef ivoc_config_h -#define ivoc_config_h +#pragma once #if __GNUC__ #define NO_MULT_INHERIT 1 #endif - -#endif diff --git a/src/ivoc/ivocvect.h b/src/ivoc/ivocvect.h index 418ec3789b..f71e32ff7f 100644 --- a/src/ivoc/ivocvect.h +++ b/src/ivoc/ivocvect.h @@ -1,5 +1,4 @@ -#ifndef ivoc_vector_h -#define ivoc_vector_h +#pragma once #include "nrnmutdec.h" #include "ocnotify.h" @@ -121,5 +120,3 @@ extern void vector_set_label(IvocVect*, char*); // olupton 2022-01-21: backwards compatibility using Vect = IvocVect; - -#endif diff --git a/src/ivoc/mymath.h b/src/ivoc/mymath.h index a9bfb8d040..34ea982c6e 100644 --- a/src/ivoc/mymath.h +++ b/src/ivoc/mymath.h @@ -1,5 +1,4 @@ -#ifndef mymath_h -#define mymath_h +#pragma once #include @@ -96,5 +95,3 @@ inline bool MyMath::inside(Coord x, Coord x1, Coord x2) { inline bool MyMath::inside(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2) { return inside(x, x1, x2) && inside(y, y1, y2); } - -#endif diff --git a/src/ivoc/nrngsl.h b/src/ivoc/nrngsl.h index efb1256bee..fca17766a6 100644 --- a/src/ivoc/nrngsl.h +++ b/src/ivoc/nrngsl.h @@ -1,5 +1,4 @@ -#ifndef nrngsl_h -#define nrngsl_h +#pragma once #define BASE double #define GSL_ERROR(a, b) hoc_execerror(a, "b") @@ -9,4 +8,3 @@ int FUNCTION(gsl_fft_halfcomplex, radix2_transform)(BASE data[], const size_t stride, const size_t n); -#endif diff --git a/src/ivoc/nrnsymdiritem.h b/src/ivoc/nrnsymdiritem.h index bb7ab96871..02bd609833 100644 --- a/src/ivoc/nrnsymdiritem.h +++ b/src/ivoc/nrnsymdiritem.h @@ -1,5 +1,4 @@ -#ifndef nrnsymdiritem_h -#define nrnsymdiritem_h +#pragma once // allow communication between src/ivoc/symdir.cpp and src/nrniv/pysecname.cpp @@ -35,5 +34,3 @@ class SymbolItem { }; void nrn_symdir_load_pysec(std::vector& sl, void*); - -#endif diff --git a/src/ivoc/objcmd.h b/src/ivoc/objcmd.h index bb54aefa51..68ffefd7c9 100644 --- a/src/ivoc/objcmd.h +++ b/src/ivoc/objcmd.h @@ -1,5 +1,4 @@ -#ifndef objcmd_h -#define objcmd_h +#pragma once #include @@ -63,5 +62,3 @@ class HocCommandTool: public Rubberband { HocCommand* hc_; }; #endif - -#endif diff --git a/src/ivoc/oc2iv.h b/src/ivoc/oc2iv.h index d75483a7b4..a90c60ca79 100644 --- a/src/ivoc/oc2iv.h +++ b/src/ivoc/oc2iv.h @@ -1,5 +1,4 @@ -#ifndef oc2iv_h -#define oc2iv_h +#pragma once #include #include @@ -108,5 +107,3 @@ class ParseTopLevel { bool restored_; }; #endif - -#endif diff --git a/src/ivoc/ocbox.h b/src/ivoc/ocbox.h index 586b2e73f1..4b9eca01e7 100644 --- a/src/ivoc/ocbox.h +++ b/src/ivoc/ocbox.h @@ -1,5 +1,4 @@ -#ifndef ocbox_h -#define ocbox_h +#pragma once #include "ocglyph.h" @@ -35,5 +34,3 @@ class OcBox: public OcGlyphContainer { private: OcBoxImpl* bi_; }; - -#endif diff --git a/src/ivoc/ocbrowsr.h b/src/ivoc/ocbrowsr.h index 4ab28bbfb4..bdd30bacba 100644 --- a/src/ivoc/ocbrowsr.h +++ b/src/ivoc/ocbrowsr.h @@ -1,5 +1,4 @@ -#ifndef ocbrowser_h -#define ocbrowser_h +#pragma once #include @@ -14,5 +13,3 @@ class OcBrowser: public FileBrowser { virtual void accept(); virtual void select_and_adjust(GlyphIndex); }; - -#endif diff --git a/src/ivoc/ocdeck.h b/src/ivoc/ocdeck.h index 4b1c65cc55..141c317b51 100644 --- a/src/ivoc/ocdeck.h +++ b/src/ivoc/ocdeck.h @@ -1,5 +1,4 @@ -#ifndef ocdeck_h -#define ocdeck_h +#pragma once #include "ocglyph.h" @@ -21,5 +20,3 @@ class OcDeck: public OcGlyphContainer { private: OcDeckImpl* bi_; }; - -#endif diff --git a/src/ivoc/ocfile.h b/src/ivoc/ocfile.h index 046fe083fc..e04d4041c7 100644 --- a/src/ivoc/ocfile.h +++ b/src/ivoc/ocfile.h @@ -1,5 +1,4 @@ -#ifndef ocfile_h -#define ocfile_h +#pragma once #include class File; @@ -64,5 +63,3 @@ class OcFile { bool isDirExist(const std::string& path); bool makePath(const std::string& path); - -#endif diff --git a/src/ivoc/ocglyph.h b/src/ivoc/ocglyph.h index d0352a3291..3c6360959f 100644 --- a/src/ivoc/ocglyph.h +++ b/src/ivoc/ocglyph.h @@ -1,5 +1,4 @@ -#ifndef ocglyph_h -#define ocglyph_h +#pragma once #include class PrintableWindow; @@ -56,5 +55,3 @@ class OcGlyphContainer: public OcGlyph { OcGlyphContainer* parent_; bool recurse_; }; - -#endif diff --git a/src/ivoc/oclist.h b/src/ivoc/oclist.h index 9fd7a1b06c..e387fdfd88 100644 --- a/src/ivoc/oclist.h +++ b/src/ivoc/oclist.h @@ -1,5 +1,4 @@ -#ifndef oclist_h -#define oclist_h +#pragma once #include @@ -41,5 +40,3 @@ class OcList: public Resource, public Observer { OcListBrowser* b_; cTemplate* ct_; }; - -#endif diff --git a/src/ivoc/ocmatrix.h b/src/ivoc/ocmatrix.h index 5754e51b96..15960fe51f 100644 --- a/src/ivoc/ocmatrix.h +++ b/src/ivoc/ocmatrix.h @@ -1,5 +1,4 @@ -#ifndef ocmatrix_h -#define ocmatrix_h +#pragma once #include #include @@ -224,5 +223,3 @@ class OcSparseMatrix final: public OcMatrix { // type 2 Eigen::SparseMatrix m_{}; std::unique_ptr> lu_{}; }; - -#endif diff --git a/src/ivoc/ocobserv.h b/src/ivoc/ocobserv.h index d0331ce5f9..f7be547c79 100644 --- a/src/ivoc/ocobserv.h +++ b/src/ivoc/ocobserv.h @@ -1,5 +1,4 @@ -#ifndef ocobserve_h -#define ocobserve_h +#pragma once #include "oc_ansi.h" @@ -61,5 +60,3 @@ class ClassObservable: public Observable { int message_; int cnt_; }; - -#endif diff --git a/src/ivoc/ocpicker.h b/src/ivoc/ocpicker.h index c885d12eb6..6e7dfec786 100644 --- a/src/ivoc/ocpicker.h +++ b/src/ivoc/ocpicker.h @@ -1,5 +1,4 @@ -#ifndef ocpicker_h -#define ocpicker_h +#pragma once #include @@ -70,4 +69,3 @@ class StandardPicker { EventButton mb_; std::vector* handlers_[unknown]; }; -#endif diff --git a/src/ivoc/ocpointer.h b/src/ivoc/ocpointer.h index 9a7dabf905..6c3116baa4 100644 --- a/src/ivoc/ocpointer.h +++ b/src/ivoc/ocpointer.h @@ -1,5 +1,4 @@ -#ifndef ocpointer_h -#define ocpointer_h +#pragma once #include #include "oc2iv.h" @@ -27,5 +26,3 @@ class StmtInfo { Symlist* symlist_; Symbol* symstmt_; }; - -#endif diff --git a/src/ivoc/rect.h b/src/ivoc/rect.h index 74865e1db7..d0c9285f10 100644 --- a/src/ivoc/rect.h +++ b/src/ivoc/rect.h @@ -1,5 +1,4 @@ -#ifndef rect_h -#define rect_h +#pragma once #undef Rect #define Rect nrn_Rect @@ -157,5 +156,3 @@ inline void Rect::width(Coord x) { inline void Rect::height(Coord x) { h_ = (x > 0) ? x : 1.; } - -#endif diff --git a/src/ivoc/rubband.h b/src/ivoc/rubband.h index 50b9ca721b..ae72eace1a 100644 --- a/src/ivoc/rubband.h +++ b/src/ivoc/rubband.h @@ -1,5 +1,4 @@ -#ifndef rubberband_h -#define rubberband_h +#pragma once #include #include @@ -161,5 +160,3 @@ inline Coord Rubberband::y_begin() const { void RubberCallback(T)::execute(Rubberband* rb) { \ (obj_->*func_)(rb); \ } - -#endif diff --git a/src/ivoc/scenepic.h b/src/ivoc/scenepic.h index 60d9e43e58..b9bea17dbd 100644 --- a/src/ivoc/scenepic.h +++ b/src/ivoc/scenepic.h @@ -1,5 +1,4 @@ -#ifndef scenepicker_h -#define scenepicker_h +#pragma once #include #include "ocpicker.h" @@ -53,5 +52,3 @@ class ScenePicker: public StandardPicker { private: ScenePickerImpl* spi_; }; - -#endif diff --git a/src/ivoc/scenevie.h b/src/ivoc/scenevie.h index 51de7ebaf7..46b6692bba 100644 --- a/src/ivoc/scenevie.h +++ b/src/ivoc/scenevie.h @@ -1,5 +1,4 @@ -#ifndef sceneview_h -#define sceneview_h +#pragma once /* A universe where data is placed is a scene. There can be 0 or many @@ -365,6 +364,3 @@ inline Coord Scene::y1() const { inline Coord Scene::y2() const { return y2_; } - - -#endif diff --git a/src/ivoc/symchoos.h b/src/ivoc/symchoos.h index dc465fe355..147164bb5a 100644 --- a/src/ivoc/symchoos.h +++ b/src/ivoc/symchoos.h @@ -27,8 +27,7 @@ * SymChooser -- select a Symbol */ -#ifndef symchooser_h -#define symchooser_h +#pragma once #include #include @@ -66,5 +65,3 @@ class SymChooser: public Dialog { }; #include - -#endif diff --git a/src/ivoc/symdir.h b/src/ivoc/symdir.h index 02b1c1e44a..05a5500138 100644 --- a/src/ivoc/symdir.h +++ b/src/ivoc/symdir.h @@ -1,5 +1,4 @@ -#ifndef symdir_h -#define symdir_h +#pragma once #include #include @@ -56,5 +55,3 @@ class SymDirectory: public Resource { private: SymDirectoryImpl* impl_; }; - -#endif diff --git a/src/ivoc/utility.h b/src/ivoc/utility.h index 83cc7f5f9d..e20553bb47 100644 --- a/src/ivoc/utility.h +++ b/src/ivoc/utility.h @@ -1,5 +1,4 @@ -#ifndef utility_h -#define utility_h +#pragma once #include #include @@ -87,5 +86,3 @@ class K { }; void handle_old_focus(); - -#endif diff --git a/src/ivoc/xmenu.h b/src/ivoc/xmenu.h index 929bb84511..71a38eaec2 100644 --- a/src/ivoc/xmenu.h +++ b/src/ivoc/xmenu.h @@ -1,5 +1,4 @@ -#ifndef xmenu_h -#define xmenu_h +#pragma once #include #include @@ -511,6 +510,3 @@ class HocStateMenuItem: public HocUpdateItem, public Observer { MenuItem* b_; HocAction* action_; }; - - -#endif diff --git a/src/ivos/InterViews/coord.h b/src/ivos/InterViews/coord.h index 65eb21480f..9ffe2306b3 100755 --- a/src/ivos/InterViews/coord.h +++ b/src/ivos/InterViews/coord.h @@ -26,8 +26,7 @@ * Coordinates for graphics allocation and rendering. */ -#ifndef iv_coord_h -#define iv_coord_h +#pragma once #include @@ -48,5 +47,3 @@ typedef int _lib_iv2_6(Coord); extern double inch, inches, cm, mm, point, points; static const int pixels = 1; - -#endif diff --git a/src/ivos/InterViews/enter-scope.h b/src/ivos/InterViews/enter-scope.h index 530363dd6c..288d354100 100644 --- a/src/ivos/InterViews/enter-scope.h +++ b/src/ivos/InterViews/enter-scope.h @@ -22,8 +22,7 @@ * OF THIS SOFTWARE. */ -#ifndef iv__scope_h -#define iv__scope_h +#pragma once #include @@ -46,5 +45,3 @@ #endif #endif - -#endif diff --git a/src/ivos/InterViews/geometry.h b/src/ivos/InterViews/geometry.h index 50c5be3eee..72f61eebc7 100644 --- a/src/ivos/InterViews/geometry.h +++ b/src/ivos/InterViews/geometry.h @@ -22,8 +22,7 @@ * OF THIS SOFTWARE. */ -#ifndef iv_geometry_h -#define iv_geometry_h +#pragma once #include @@ -297,5 +296,3 @@ inline Coord Extension::right() const { return x_end_; } inline Coord Extension::top() const { return y_end_; } #include - -#endif diff --git a/src/ivos/InterViews/iv.h b/src/ivos/InterViews/iv.h index 8f8e2f958c..fdc6e6c2f7 100755 --- a/src/ivos/InterViews/iv.h +++ b/src/ivos/InterViews/iv.h @@ -22,8 +22,7 @@ * OF THIS SOFTWARE. */ -#ifndef _lib_iv_h -#define _lib_iv_h +#pragma once #if 1 || defined(__STDC__) || defined(__ANSI_CPP__) #define _lib_iv(name) iv##name @@ -32,5 +31,3 @@ #define _lib_iv(name) iv/**/name #define _lib_iv2_6(name) iv2_6_/**/name #endif - -#endif diff --git a/src/ivos/InterViews/observe.h b/src/ivos/InterViews/observe.h index 48490e717f..71aefe67f1 100755 --- a/src/ivos/InterViews/observe.h +++ b/src/ivos/InterViews/observe.h @@ -26,8 +26,7 @@ * Observable - object to observe */ -#ifndef iv_observe_h -#define iv_observe_h +#pragma once #include @@ -59,5 +58,3 @@ class Observer { }; #include - -#endif diff --git a/src/ivos/InterViews/resource.h b/src/ivos/InterViews/resource.h index bf487f2dfb..459b7e5847 100644 --- a/src/ivos/InterViews/resource.h +++ b/src/ivos/InterViews/resource.h @@ -26,8 +26,7 @@ * Resources are shared objects. */ -#ifndef iv_resource_h -#define iv_resource_h +#pragma once #include @@ -65,5 +64,3 @@ class Resource { */ static inline void Unref(const Resource* r) { Resource::unref(r); } - -#endif diff --git a/src/ivos/OS/os.h b/src/ivos/OS/os.h index e64b641153..ca6bb5281d 100755 --- a/src/ivos/OS/os.h +++ b/src/ivos/OS/os.h @@ -22,13 +22,10 @@ * OF THIS SOFTWARE. */ -#ifndef _lib_os_h -#define _lib_os_h +#pragma once #if 1 || defined(__STDC__) || defined(__ANSI_CPP__) #define _lib_os(name) os##name #else #define _lib_os(name) os/**/name #endif - -#endif diff --git a/src/nrncvode/cvodeobj.h b/src/nrncvode/cvodeobj.h index 54558af45d..d441a63b02 100644 --- a/src/nrncvode/cvodeobj.h +++ b/src/nrncvode/cvodeobj.h @@ -1,5 +1,4 @@ -#ifndef cvodeobj_h -#define cvodeobj_h +#pragma once #include "nrnmpi.h" #include "nrnneosm.h" @@ -267,5 +266,3 @@ class Cvode { int opmode_; // 1 advance, 2 interpolate, 3 init; for testing #endif // NRNMPI }; - -#endif diff --git a/src/nrncvode/netcon.h b/src/nrncvode/netcon.h index 107e25fd64..efa9d68657 100644 --- a/src/nrncvode/netcon.h +++ b/src/nrncvode/netcon.h @@ -1,5 +1,4 @@ -#ifndef netcon_h -#define netcon_h +#pragma once #undef check @@ -417,5 +416,3 @@ class NetParEvent: public DiscreteEvent { }; extern PreSyn* nrn_gid2outputpresyn(int gid); - -#endif diff --git a/src/nrncvode/netcvode.h b/src/nrncvode/netcvode.h index 65d0765887..6715eae018 100644 --- a/src/nrncvode/netcvode.h +++ b/src/nrncvode/netcvode.h @@ -1,5 +1,4 @@ -#ifndef netcvode_h -#define netcvode_h +#pragma once #define PRINT_EVENT 1 @@ -262,5 +261,3 @@ class NetCvode { void allthread_handle(); HocEventList* allthread_hocevents_; }; - -#endif diff --git a/src/nrncvode/nrndaspk.h b/src/nrncvode/nrndaspk.h index 60bd36334e..6826a25b69 100644 --- a/src/nrncvode/nrndaspk.h +++ b/src/nrncvode/nrndaspk.h @@ -1,5 +1,4 @@ -#ifndef daspk_h -#define daspk_h +#pragma once #include "shared/nvector_serial.h" #include "nvector_nrnthread.h" @@ -37,4 +36,3 @@ class Daspk { static int init_try_again_; static int first_try_init_failures_; }; -#endif diff --git a/src/nrncvode/pool.hpp b/src/nrncvode/pool.hpp index c062e93ad3..037224a3e5 100644 --- a/src/nrncvode/pool.hpp +++ b/src/nrncvode/pool.hpp @@ -1,5 +1,4 @@ -#ifndef pool_h -#define pool_h +#pragma once // create and manage a vector of objects as a memory pool of those objects // the object must have a void clear() method which takes care of any @@ -130,6 +129,3 @@ void MutexPool::free_all() { put_ = 0; MUTUNLOCK } - - -#endif diff --git a/src/nrncvode/vrecitem.h b/src/nrncvode/vrecitem.h index 17b8b208a0..adaafb674e 100644 --- a/src/nrncvode/vrecitem.h +++ b/src/nrncvode/vrecitem.h @@ -1,5 +1,4 @@ -#ifndef vrecitem_h -#define vrecitem_h +#pragma once #include #include @@ -328,5 +327,3 @@ class VecPlayContinuousSave: public PlayRecordSave { int discon_index_; int ubound_index_; }; - -#endif diff --git a/src/nrniv/bbsavestate.h b/src/nrniv/bbsavestate.h index 3be6f7a9ec..52ac1813c1 100644 --- a/src/nrniv/bbsavestate.h +++ b/src/nrniv/bbsavestate.h @@ -1,5 +1,4 @@ -#ifndef bbsavestate_h -#define bbsavestate_h +#pragma once #include "neuron/container/data_handle.hpp" struct Object; @@ -120,5 +119,3 @@ void bbss_save_done(void* bbss); * cleanup. When this call returns, bbss will be invalid. */ void bbss_restore_done(void* bbss); - -#endif diff --git a/src/nrniv/glinerec.h b/src/nrniv/glinerec.h index 287358c620..9da5029eb3 100644 --- a/src/nrniv/glinerec.h +++ b/src/nrniv/glinerec.h @@ -1,5 +1,4 @@ -#ifndef glinerec_h -#define glinerec_h +#pragma once #include "nrnoc2iv.h" #include "vrecitem.h" @@ -56,5 +55,3 @@ class GVectorRecord: public PlayRecord { neuron::container::data_handle pdata(int); GraphVector* gv_; }; - -#endif diff --git a/src/nrniv/kschan.h b/src/nrniv/kschan.h index b3fd32a26d..fe7b2b13ae 100644 --- a/src/nrniv/kschan.h +++ b/src/nrniv/kschan.h @@ -1,5 +1,4 @@ -#ifndef kschan_h -#define kschan_h +#pragma once #include #include "nrnoc2iv.h" @@ -486,5 +485,3 @@ class KSChan { std::vector parm_default{}; }; - -#endif diff --git a/src/nrniv/kssingle.h b/src/nrniv/kssingle.h index 22034ee696..eaf1c8b20f 100644 --- a/src/nrniv/kssingle.h +++ b/src/nrniv/kssingle.h @@ -1,5 +1,4 @@ -#ifndef kssingle_h -#define kssingle_h +#pragma once #include #include @@ -115,5 +114,3 @@ class KSSingleState { int ntrans_; int* transitions_; }; - -#endif diff --git a/src/nrniv/linmod.h b/src/nrniv/linmod.h index 090d054456..479ceb6d51 100644 --- a/src/nrniv/linmod.h +++ b/src/nrniv/linmod.h @@ -1,5 +1,4 @@ -#ifndef linmod_h -#define linmod_h +#pragma once #include "ocmatrix.h" #include "ivocvect.h" @@ -31,5 +30,3 @@ class LinearModelAddition: public NrnDAE { Vect& b_; Object* f_callable_; }; - -#endif diff --git a/src/nrniv/matrixmap.h b/src/nrniv/matrixmap.h index 4838d24af4..eba8b892d7 100644 --- a/src/nrniv/matrixmap.h +++ b/src/nrniv/matrixmap.h @@ -1,5 +1,4 @@ -#ifndef matrixmap_h -#define matrixmap_h +#pragma once #include "ocmatrix.h" #include "nrnoc2iv.h" @@ -121,5 +120,3 @@ class MatrixMap { double** pm_; double** ptree_; }; - -#endif diff --git a/src/nrniv/multisplitcontrol.h b/src/nrniv/multisplitcontrol.h index 7a1ebc6506..d42647056f 100644 --- a/src/nrniv/multisplitcontrol.h +++ b/src/nrniv/multisplitcontrol.h @@ -1,5 +1,4 @@ -#ifndef multisplitcontrol_h -#define multisplitcontrol_h +#pragma once class MultiSplitThread { public: @@ -84,5 +83,3 @@ class MultiSplitControl { int nth_; MultiSplitThread* mth_; }; - -#endif diff --git a/src/nrniv/ndatclas.h b/src/nrniv/ndatclas.h index 83f3ab0acb..c906bd3a23 100644 --- a/src/nrniv/ndatclas.h +++ b/src/nrniv/ndatclas.h @@ -1,5 +1,4 @@ -#ifndef nrn_dataclass_h -#define nrn_dataclass_h +#pragma once #include @@ -40,5 +39,3 @@ class SectionList: public Resource { private: SectionListImpl* sli_; }; - -#endif diff --git a/src/nrniv/nonlinz.h b/src/nrniv/nonlinz.h index b477bf783a..30d40a8d53 100644 --- a/src/nrniv/nonlinz.h +++ b/src/nrniv/nonlinz.h @@ -1,5 +1,4 @@ -#ifndef nonlinz_h -#define nonlinz_h +#pragma once class NonLinImpRep; @@ -22,5 +21,3 @@ class NonLinImp { private: NonLinImpRep* rep_{}; }; - -#endif diff --git a/src/nrniv/nrncore_write.h b/src/nrniv/nrncore_write.h index 15e3eed834..44dc90cda4 100644 --- a/src/nrniv/nrncore_write.h +++ b/src/nrniv/nrncore_write.h @@ -1,11 +1,7 @@ -#ifndef nrncore_write_h -#define nrncore_write_h +#pragma once #include "nrncore_write/data/cell_group.h" int nrncore_run(const char* arg); int nrncore_is_enabled(); int nrncore_psolve(double tstop, int file_mode); - - -#endif // nrncore_write_h diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h index b93b0cd53f..8bc9941a21 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h @@ -1,5 +1,4 @@ -#ifndef NRN_NRNCORE_CALLBACKS_H -#define NRN_NRNCORE_CALLBACKS_H +#pragma once #include #include @@ -263,5 +262,3 @@ static core2nrn_callback_t cnbs[] = { void map_coreneuron_callbacks(void* handle); - -#endif // NRN_NRNCORE_CALLBACKS_H diff --git a/src/nrniv/nrncore_write/data/cell_group.h b/src/nrniv/nrncore_write/data/cell_group.h index 77962a3d5d..374c2a2510 100644 --- a/src/nrniv/nrncore_write/data/cell_group.h +++ b/src/nrniv/nrncore_write/data/cell_group.h @@ -1,5 +1,4 @@ -#ifndef NRN_CELL_GROUP_H -#define NRN_CELL_GROUP_H +#pragma once #include "datum_indices.h" #include @@ -90,5 +89,3 @@ class CellGroup { return p->id().current_row() - sorted_token.thread_cache(tid).mechanism_offset.at(type); } }; - -#endif // NRN_CELL_GROUP_H diff --git a/src/nrniv/nrncore_write/data/datum_indices.h b/src/nrniv/nrncore_write/data/datum_indices.h index 705e7743a6..46df3ba67c 100644 --- a/src/nrniv/nrncore_write/data/datum_indices.h +++ b/src/nrniv/nrncore_write/data/datum_indices.h @@ -1,5 +1,4 @@ -#ifndef NRN_DATUM_INDICES_H -#define NRN_DATUM_INDICES_H +#pragma once // assume all Datum.pval point into this cell. In practice, this holds because // they point either to the area or an ion property of the given node. @@ -14,5 +13,3 @@ class DatumIndices { int* ion_type; // negative codes semantics, positive codes mechanism type int* ion_index; // index of range variable relative to beginning of that type }; - -#endif // NRN_DATUM_INDICES_H diff --git a/src/nrniv/nrncore_write/io/nrncore_io.h b/src/nrniv/nrncore_write/io/nrncore_io.h index d191de5f89..674a502567 100644 --- a/src/nrniv/nrncore_write/io/nrncore_io.h +++ b/src/nrniv/nrncore_write/io/nrncore_io.h @@ -1,5 +1,4 @@ -#ifndef NRN_NRNCORE_IO_H -#define NRN_NRNCORE_IO_H +#pragma once #include "hocdec.h" #include @@ -44,6 +43,3 @@ void write_nrnthread_task(const char*, CellGroup* cgs, bool append); void nrnbbcore_vecplay_write(FILE* f, NrnThread& nt); void nrn_write_mapping_info(const char* path, int gid, NrnMappingInfo& minfo); - - -#endif // NRN_NRNCORE_IO_H diff --git a/src/nrniv/nrndae.h b/src/nrniv/nrndae.h index bf0817e1f8..94ead2ad16 100644 --- a/src/nrniv/nrndae.h +++ b/src/nrniv/nrndae.h @@ -9,8 +9,7 @@ * form \f[$C \frac{dy}{dt} = A y + b$\f]. */ -#ifndef nrndae_h -#define nrndae_h +#pragma once #include "ivocvect.h" #include "matrixmap.h" @@ -222,5 +221,3 @@ void nrndae_deregister(NrnDAE* n); typedef std::list NrnDAEPtrList; typedef NrnDAEPtrList::const_iterator NrnDAEPtrListIterator; - -#endif diff --git a/src/nrniv/nrnmenu.h b/src/nrniv/nrnmenu.h index d55cd0557e..c07933ede5 100644 --- a/src/nrniv/nrnmenu.h +++ b/src/nrniv/nrnmenu.h @@ -1,5 +1,4 @@ -#ifndef nrnmenu_h -#define nrnmenu_h +#pragma once #include "ndatclas.h" class MechTypeImpl; @@ -74,5 +73,3 @@ class MechanismType: public Resource { private: MechTypeImpl* mti_; }; - -#endif diff --git a/src/nrniv/nrnoc2iv.h b/src/nrniv/nrnoc2iv.h index b83f31c3a3..efd9afc54e 100644 --- a/src/nrniv/nrnoc2iv.h +++ b/src/nrniv/nrnoc2iv.h @@ -1,5 +1,4 @@ -#ifndef nrnoc2iv_h -#define nrnoc2iv_h +#pragma once // common things in nrnoc that can be used by nrniv #include "oc2iv.h" @@ -7,5 +6,3 @@ #include "section.h" #include "ndatclas.h" - -#endif diff --git a/src/nrniv/nrnsection_mapping.h b/src/nrniv/nrnsection_mapping.h index 5ebeaf2a78..3fb8f29fa5 100644 --- a/src/nrniv/nrnsection_mapping.h +++ b/src/nrniv/nrnsection_mapping.h @@ -1,5 +1,4 @@ -#ifndef NRN_SECTION_MAPPING -#define NRN_SECTION_MAPPING +#pragma once #include #include @@ -144,5 +143,3 @@ struct NrnMappingInfo { }; void nrn_write_mapping_info(const char*, int, NrnMappingInfo&); - -#endif // NRN_SECTION_MAPPING diff --git a/src/nrniv/nvector_nrnparallel_ld.h b/src/nrniv/nvector_nrnparallel_ld.h index 4684857d45..f7d5bd6c62 100644 --- a/src/nrniv/nvector_nrnparallel_ld.h +++ b/src/nrniv/nvector_nrnparallel_ld.h @@ -60,9 +60,7 @@ mv temp nvector_nrnparallel_ld.cpp * ----------------------------------------------------------------- */ -#ifndef _NVECTOR_NRNPARALLEL_LD_H -#define _NVECTOR_NRNPARALLEL_LD_H - +#pragma once #include #define MPI_Comm int @@ -316,6 +314,3 @@ void N_VCompare_NrnParallelLD(realtype c, N_Vector x, N_Vector z); booleantype N_VInvTest_NrnParallelLD(N_Vector x, N_Vector z); booleantype N_VConstrMask_NrnParallelLD(N_Vector c, N_Vector x, N_Vector m); realtype N_VMinQuotient_NrnParallelLD(N_Vector num, N_Vector denom); - - -#endif diff --git a/src/nrniv/nvector_nrnserial_ld.h b/src/nrniv/nvector_nrnserial_ld.h index aeb22f0050..a5ff42dd7c 100644 --- a/src/nrniv/nvector_nrnserial_ld.h +++ b/src/nrniv/nvector_nrnserial_ld.h @@ -60,9 +60,7 @@ mv temp nvector_nrnserial_ld.cpp * ----------------------------------------------------------------- */ -#ifndef _NVECTOR_NRNSERIAL_LD_H -#define _NVECTOR_NRNSERIAL_LD_H - +#pragma once #include "nvector.h" #include "sundialstypes.h" @@ -280,6 +278,3 @@ void N_VCompare_NrnSerialLD(realtype c, N_Vector x, N_Vector z); booleantype N_VInvTest_NrnSerialLD(N_Vector x, N_Vector z); booleantype N_VConstrMask_NrnSerialLD(N_Vector c, N_Vector x, N_Vector m); realtype N_VMinQuotient_NrnSerialLD(N_Vector num, N_Vector denom); - - -#endif diff --git a/src/nrniv/nvector_nrnthread.h b/src/nrniv/nvector_nrnthread.h index 2b20403776..24ab564b1c 100644 --- a/src/nrniv/nvector_nrnthread.h +++ b/src/nrniv/nvector_nrnthread.h @@ -53,9 +53,7 @@ * ----------------------------------------------------------------- */ -#ifndef _NVECTOR_NRNTHREAD_H -#define _NVECTOR_NRNTHREAD_H - +#pragma once #include "nvector.h" #include "sundialstypes.h" @@ -289,6 +287,3 @@ void N_VCompare_NrnThread(realtype c, N_Vector x, N_Vector z); booleantype N_VInvTest_NrnThread(N_Vector x, N_Vector z); booleantype N_VConstrMask_NrnThread(N_Vector c, N_Vector x, N_Vector m); realtype N_VMinQuotient_NrnThread(N_Vector num, N_Vector denom); - - -#endif diff --git a/src/nrniv/nvector_nrnthread_ld.h b/src/nrniv/nvector_nrnthread_ld.h index 8c8c87c591..a0dd9467f0 100644 --- a/src/nrniv/nvector_nrnthread_ld.h +++ b/src/nrniv/nvector_nrnthread_ld.h @@ -59,9 +59,7 @@ mv temp nvector_nrnthread_ld.h * ----------------------------------------------------------------- */ -#ifndef _NVECTOR_NRNTHREAD_LD_H -#define _NVECTOR_NRNTHREAD_LD_H - +#pragma once #include "nvector.h" #include "sundialstypes.h" @@ -298,6 +296,3 @@ void N_VCompare_NrnThreadLD(realtype c, N_Vector x, N_Vector z); booleantype N_VInvTest_NrnThreadLD(N_Vector x, N_Vector z); booleantype N_VConstrMask_NrnThreadLD(N_Vector c, N_Vector x, N_Vector m); realtype N_VMinQuotient_NrnThreadLD(N_Vector num, N_Vector denom); - - -#endif diff --git a/src/nrniv/ppshape.h b/src/nrniv/ppshape.h index b2d6003c34..943cf5d742 100644 --- a/src/nrniv/ppshape.h +++ b/src/nrniv/ppshape.h @@ -1,5 +1,4 @@ -#ifndef ppshape_h -#define ppshape_h +#pragma once // shape class for viewing point processes @@ -36,5 +35,3 @@ class PPShape: public ShapeScene { private: PPShapeImpl* si_; }; - -#endif diff --git a/src/nrniv/rot3band.h b/src/nrniv/rot3band.h index 8f0e4ee1a3..11c78baf1c 100644 --- a/src/nrniv/rot3band.h +++ b/src/nrniv/rot3band.h @@ -1,5 +1,4 @@ -#ifndef rot3band_h -#define rot3band_h +#pragma once /* 3-D rubberband @@ -35,5 +34,3 @@ class Rotate3Band: public Rubberband { Rotation3d* rot_; float x_old_, y_old_; }; - -#endif diff --git a/src/nrniv/rotate3d.h b/src/nrniv/rotate3d.h index 93834072d1..65ff8d65b8 100644 --- a/src/nrniv/rotate3d.h +++ b/src/nrniv/rotate3d.h @@ -1,5 +1,4 @@ -#ifndef rotation3d_h -#define rotation3d_h +#pragma once /* 3-D rotation matrix */ @@ -29,4 +28,3 @@ class Rotation3d: public Resource { float a_[3][3]; float o_[2][3]; }; -#endif diff --git a/src/nrniv/secbrows.h b/src/nrniv/secbrows.h index 22039a3f05..46037a8b8c 100644 --- a/src/nrniv/secbrows.h +++ b/src/nrniv/secbrows.h @@ -1,5 +1,4 @@ -#ifndef secbrowser_h -#define secbrowser_h +#pragma once #include #include "ocbrowsr.h" @@ -94,5 +93,3 @@ class PointProcessBrowser: public OcBrowser { private: PPBImpl* ppbi_; }; - -#endif diff --git a/src/nrniv/shape.h b/src/nrniv/shape.h index fdf0ccfc67..1bdbc1ad56 100644 --- a/src/nrniv/shape.h +++ b/src/nrniv/shape.h @@ -1,5 +1,4 @@ -#ifndef shape_h -#define shape_h +#pragma once #include "scenevie.h" #include "graph.h" @@ -178,5 +177,3 @@ class SectionHandler: public Handler { private: ShapeSection* ss_; }; - -#endif diff --git a/src/nrniv/shapeplt.h b/src/nrniv/shapeplt.h index b488b35cbb..e884dbb4df 100644 --- a/src/nrniv/shapeplt.h +++ b/src/nrniv/shapeplt.h @@ -1,6 +1,4 @@ -#ifndef shapeplot_h -#define shapeplot_h - +#pragma once #if HAVE_IV #include "shape.h" @@ -124,4 +122,3 @@ class Hinton: public Observer, public FastShape { ShapeScene* ss_; }; #endif -#endif diff --git a/src/nrniv/structpool.h b/src/nrniv/structpool.h index 452753c956..ab8999af61 100644 --- a/src/nrniv/structpool.h +++ b/src/nrniv/structpool.h @@ -1,5 +1,4 @@ -#ifndef structpool_h -#define structpool_h +#pragma once // same as ../nrncvode/pool.h but items do not require a clear method. @@ -147,5 +146,3 @@ void Pool::free_all() { assert(put_ == count_); put_ = 0; } - -#endif diff --git a/src/nrnmpi/mpispike.h b/src/nrnmpi/mpispike.h index d9d031810a..bdf2042ec1 100644 --- a/src/nrnmpi/mpispike.h +++ b/src/nrnmpi/mpispike.h @@ -1,5 +1,4 @@ -#ifndef nrnmpispike_h -#define nrnmpispike_h +#pragma once #ifndef nrn_spikebuf_size #define nrn_spikebuf_size 0 @@ -19,6 +18,3 @@ typedef struct { extern NRNMPI_Spikebuf* spbufout_; extern NRNMPI_Spikebuf* spbufin_; #endif - - -#endif diff --git a/src/nrnmpi/nrnmpidec.h b/src/nrnmpi/nrnmpidec.h index 34dc84782d..6db44a6e90 100644 --- a/src/nrnmpi/nrnmpidec.h +++ b/src/nrnmpi/nrnmpidec.h @@ -4,8 +4,7 @@ be of the form "type foo(type arg, ...)". Moreover, the * needs to be attached to the type, e.g. `T*` is valid, but `T *` isn't. */ -#ifndef nrnmpidec_h -#define nrnmpidec_h +#pragma once #include #include using longdbl = long double; @@ -131,6 +130,4 @@ extern int nrnmpi_multisend_conserve(int nsend, int nrecv); #endif // clang-format on } - -#endif #endif diff --git a/src/nrnoc/cabvars.h b/src/nrnoc/cabvars.h index 9c9d6c879d..cb3aa81f07 100644 --- a/src/nrnoc/cabvars.h +++ b/src/nrnoc/cabvars.h @@ -1,6 +1,5 @@ /* /local/src/master/nrn/src/nrnoc/cabvars.h,v 1.5 1999/02/05 18:09:50 hines Exp */ -#ifndef NRN_CABVARS_H -#define NRN_CABVARS_H +#pragma once #define XMECH 0 @@ -74,5 +73,3 @@ extern void morph_alloc(Prop*); extern std::vector memb_func; - -#endif // NRN_CABVARS_H diff --git a/src/nrnoc/gui-redirect.h b/src/nrnoc/gui-redirect.h index e2eba69b28..9b5b0af0bd 100644 --- a/src/nrnoc/gui-redirect.h +++ b/src/nrnoc/gui-redirect.h @@ -1,5 +1,4 @@ -#ifndef gui_redirect_h -#define gui_redirect_h +#pragma once #include "hocdec.h" #include "nrnpy.h" @@ -89,5 +88,3 @@ extern Object* nrn_get_gui_redirect_obj(); } \ } \ } - -#endif diff --git a/src/nrnoc/md1redef.h b/src/nrnoc/md1redef.h index b8dfcc65a8..e323dc4832 100644 --- a/src/nrnoc/md1redef.h +++ b/src/nrnoc/md1redef.h @@ -1,5 +1,4 @@ -#ifndef nmodl1_redef_h -#define nmodl1_redef_h +#pragma once #define v _v #define area _area @@ -24,5 +23,3 @@ #define prop _prop #define nodecount _nodecount #define id _id - -#endif diff --git a/src/nrnoc/md2redef.h b/src/nrnoc/md2redef.h index 0933e0fb14..75de11c871 100755 --- a/src/nrnoc/md2redef.h +++ b/src/nrnoc/md2redef.h @@ -1,5 +1,4 @@ -#ifndef nmodl2_redef_h -#define nmodl2_redef_h +#pragma once #undef v #undef area @@ -19,5 +18,3 @@ #undef nodecount #undef id - -#endif diff --git a/src/nrnoc/nonvintblock.h b/src/nrnoc/nonvintblock.h index 66f3ed39c1..e2c14196fd 100644 --- a/src/nrnoc/nonvintblock.h +++ b/src/nrnoc/nonvintblock.h @@ -1,5 +1,4 @@ -#ifndef nonvintblock_h -#define nonvintblock_h +#pragma once /* @@ -72,6 +71,3 @@ nonvintblock_extern int ( /* multiply the existing values in y (cvode.atol()) with appropriate scale factors */ #define nrn_nonvint_block_ode_abstol(size, y, tid) nonvint_block(10, size, y, 0, tid) - - -#endif diff --git a/src/nrnoc/nrniv_mf.h b/src/nrnoc/nrniv_mf.h index aa4869f52d..1a1c016daa 100644 --- a/src/nrnoc/nrniv_mf.h +++ b/src/nrnoc/nrniv_mf.h @@ -1,5 +1,4 @@ -#ifndef nrniv_mf_h -#define nrniv_mf_h +#pragma once #include "hoc_membf.h" #include "hocdec.h" #include "membfunc.h" @@ -106,5 +105,3 @@ void* nrn_pool_alloc(void* pool); void* nrn_pool_create(long count, int itemsize); void nrn_pool_delete(void* pool); void nrn_pool_freeall(void* pool); - -#endif /* nrniv_mf_h */ diff --git a/src/nrnoc/nrnredef.h b/src/nrnoc/nrnredef.h index b5682e97cd..4fe7d5ca5f 100644 --- a/src/nrnoc/nrnredef.h +++ b/src/nrnoc/nrnredef.h @@ -1,8 +1,5 @@ -#ifndef nrnredef_h -#define nrnredef_h +#pragma once #define net_send nrn_net_send #define net_move nrn_net_move #define net_event nrn_net_event - -#endif diff --git a/src/nrnpython/hoccontext.h b/src/nrnpython/hoccontext.h index aaeef6cf22..d6f79f4a46 100644 --- a/src/nrnpython/hoccontext.h +++ b/src/nrnpython/hoccontext.h @@ -1,6 +1,4 @@ -#ifndef hoccontext_h -#define hoccontext_h - +#pragma once extern Object* hoc_thisobject; extern Objectdata* hoc_top_level_data; @@ -39,4 +37,3 @@ static void hc_restore_(HocContext* hc) { hoc_objectdata = hc->obd; hoc_symlist = hc->sl; } -#endif diff --git a/src/nrnpython/nrnpy_utils.h b/src/nrnpython/nrnpy_utils.h index 3e62b4a94e..91517b9b73 100644 --- a/src/nrnpython/nrnpy_utils.h +++ b/src/nrnpython/nrnpy_utils.h @@ -1,5 +1,4 @@ -#ifndef nrnpy_utils_h -#define nrnpy_utils_h +#pragma once #include #include @@ -194,5 +193,3 @@ extern void nrnpy_prop_referr(); return NULL; \ } \ } - -#endif /* end of include guard: nrnpy_utils_h */ diff --git a/src/nrnpython/nrnpython.h b/src/nrnpython/nrnpython.h index c20fed1b7e..cb89b7b6b2 100644 --- a/src/nrnpython/nrnpython.h +++ b/src/nrnpython/nrnpython.h @@ -1,5 +1,4 @@ -#ifndef nrnpython_h -#define nrnpython_h +#pragma once #ifdef _WIN64 #define MS_WIN64 @@ -95,4 +94,3 @@ extern "C" PyObject* nrn_hocobj_ptr(double*); int nrn_is_hocobj_ptr(PyObject*, neuron::container::data_handle&); int nrn_pointer_assign(Prop*, Symbol*, PyObject*); neuron::container::generic_data_handle* nrnpy_setpointer_helper(PyObject*, PyObject*); -#endif diff --git a/src/oc/classreg.h b/src/oc/classreg.h index 2a004a2e36..fbb4beb706 100644 --- a/src/oc/classreg.h +++ b/src/oc/classreg.h @@ -1,5 +1,4 @@ -#ifndef classreg_h -#define classreg_h +#pragma once #include #include @@ -13,6 +12,3 @@ extern void class2oc(const char*, int (*checkpoint)(void**), Member_ret_obj_func*, Member_ret_str_func*); - - -#endif diff --git a/src/oc/code.h b/src/oc/code.h index 7ecfbb0c82..e9906db78f 100644 --- a/src/oc/code.h +++ b/src/oc/code.h @@ -1,5 +1,4 @@ -#ifndef hoc_code_h -#define hoc_code_h +#pragma once #include "redef.h" @@ -50,6 +49,3 @@ extern void hoc_ifseclist(void), mech_uninsert(void); extern void simpleconnectsection(void), range_interpolate_single(void); extern void hoc_sec_internal_push(void); /* END NEWCABLE*/ - - -#endif diff --git a/src/oc/hoc.h b/src/oc/hoc.h index b781e607f3..b28db7ee01 100755 --- a/src/oc/hoc.h +++ b/src/oc/hoc.h @@ -1,6 +1,3 @@ - -#ifndef hoc_h -#define hoc_h +#pragma once #include "redef.h" #include "hocdec.h" -#endif diff --git a/src/oc/hoc_membf.h b/src/oc/hoc_membf.h index 5d4341acb2..9ac37cba06 100644 --- a/src/oc/hoc_membf.h +++ b/src/oc/hoc_membf.h @@ -1,5 +1,4 @@ -#ifndef hoc_membf_h -#define hoc_membf_h +#pragma once struct Object; @@ -17,5 +16,3 @@ typedef struct Member_ret_str_func { const char* name; const char** (*member)(void*); } Member_ret_str_func; - -#endif diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index 944d4e9d72..703b4a80af 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -1,6 +1,4 @@ - -#ifndef hocdec_h -#define hocdec_h +#pragma once #define INCLUDEHOCH 1 #include "neuron/container/generic_data_handle.hpp" @@ -295,6 +293,3 @@ int* tids; int node_num; int mytid; #endif - - -#endif diff --git a/src/oc/hocgetsym.h b/src/oc/hocgetsym.h index 85cd5eabff..30069ca3b9 100644 --- a/src/oc/hocgetsym.h +++ b/src/oc/hocgetsym.h @@ -1,5 +1,4 @@ -#ifndef hocgetsym_h -#define hocgetsym_h +#pragma once #include "hoc.h" @@ -14,5 +13,3 @@ Psym* hoc_getsym(const char*); double hoc_getsymval(Psym*); void hoc_assignsym(Psym* p, double val); void hoc_execstr(const char* cp); - -#endif diff --git a/src/oc/hoclist.h b/src/oc/hoclist.h index df4df288e6..de9666efa0 100644 --- a/src/oc/hoclist.h +++ b/src/oc/hoclist.h @@ -1,5 +1,4 @@ -#ifndef hoc_list_h -#define hoc_list_h +#pragma once #if HOC_L_LIST #define stralloc hoc_l_stralloc @@ -107,6 +106,3 @@ extern void hoc_l_replacstr(hoc_Item*, const char*); #define Lappenditem lappenditem #define Lappendlst lappendlst #define Lappendsec lappendsec - - -#endif diff --git a/src/oc/hocparse.h b/src/oc/hocparse.h index ff37e23550..1c0e04837e 100644 --- a/src/oc/hocparse.h +++ b/src/oc/hocparse.h @@ -1,5 +1,4 @@ -#ifndef hocparse_h -#define hocparse_h +#pragma once #include "hoc.h" @@ -37,6 +36,3 @@ extern void hoc_obvar_declare(Symbol* sym, int type, int pmes); extern void hoc_help(void); extern char* hoc_strgets(char*, int); extern int hoc_strgets_need(void); - - -#endif diff --git a/src/oc/hocstr.h b/src/oc/hocstr.h index b2daa5d63c..a78af64c20 100644 --- a/src/oc/hocstr.h +++ b/src/oc/hocstr.h @@ -1,5 +1,4 @@ -#ifndef hocstr_h -#define hocstr_h +#pragma once #include /* too many time char* buf overruns its storage */ @@ -14,6 +13,3 @@ extern HocStr* hocstr_create(size_t); extern void hocstr_delete(HocStr*); void hocstr_resize(HocStr*, size_t); void hocstr_copy(HocStr*, const char*); - - -#endif diff --git a/src/oc/nrnapi.h b/src/oc/nrnapi.h index 9aca825693..330ca67bd7 100644 --- a/src/oc/nrnapi.h +++ b/src/oc/nrnapi.h @@ -1,6 +1,3 @@ -#ifndef nrnapi_h -#define nrnapi_h +#pragma once #define NRNAPI 2 - -#endif diff --git a/src/oc/nrnassrt.h b/src/oc/nrnassrt.h index abd026ae66..5f0b03b2e3 100644 --- a/src/oc/nrnassrt.h +++ b/src/oc/nrnassrt.h @@ -1,5 +1,4 @@ -#ifndef nrnassrt_h -#define nrnassrt_h +#pragma once /* nrn_assert is not deactivated by -DNDEBUG. Use when the assert expression has side effects which need to be executed regardles of NDEBUG. @@ -28,6 +27,3 @@ has side effects which need to be executed regardles of NDEBUG. } \ } while (0) #endif - - -#endif diff --git a/src/oc/nrnmpi.h b/src/oc/nrnmpi.h index 259e4fa094..196e6cf2b5 100644 --- a/src/oc/nrnmpi.h +++ b/src/oc/nrnmpi.h @@ -1,5 +1,4 @@ -#ifndef nrnmpi_h -#define nrnmpi_h +#pragma once #include "nrnmpiuse.h" /* by default nrnmpi_numprocs_world = nrnmpi_numprocs = nrnmpi_numsubworlds and @@ -29,4 +28,3 @@ extern int nrn_cannot_use_threads_and_mpi; /* 0 if required <= provided from MPI #include "nrnmpidec.h" #endif /*NRNMPI*/ -#endif /*nrnmpi_h*/ diff --git a/src/oc/nrnunits.h b/src/oc/nrnunits.h index e8f777a686..2ad2640d25 100644 --- a/src/oc/nrnunits.h +++ b/src/oc/nrnunits.h @@ -1,5 +1,4 @@ -#ifndef nrnunits_modern_h -#define nrnunits_modern_h +#pragma once /** NMODL translated MOD files get unit constants typically from @@ -26,5 +25,3 @@ constexpr double _gasconstant_codata2018 = /* e/k in K/millivolt */ constexpr double _e_over_k_codata2018 = .001 * _electron_charge_codata2018 / _boltzmann_codata2018; /* 11.604518... K/mV */ - -#endif /* nrnunits_modern_h */ diff --git a/src/oc/nrnwrap_dlfcn.h b/src/oc/nrnwrap_dlfcn.h index 1a32a9e5f8..146bbf06ba 100644 --- a/src/oc/nrnwrap_dlfcn.h +++ b/src/oc/nrnwrap_dlfcn.h @@ -1,5 +1,4 @@ -#ifndef nrnwrap_dlfcn_h -#define nrnwrap_dlfcn_h +#pragma once #include "../../nrnconf.h" #if defined(HAVE_DLFCN_H) @@ -10,5 +9,3 @@ #include "../mswin/dlfcn.h" #define HAVE_DLFCN_H 1 #endif - -#endif /* nrnwrap_dlfcn_h */ diff --git a/src/oc/ocmisc.h b/src/oc/ocmisc.h index 91d6e1497f..eb864e17b7 100644 --- a/src/oc/ocmisc.h +++ b/src/oc/ocmisc.h @@ -1,5 +1,4 @@ -#ifndef ocmisc_h -#define ocmisc_h +#pragma once extern long hoc_nstack; extern long hoc_nframe; @@ -7,5 +6,3 @@ extern int hoc_errno_count; extern int hoc_pipeflag; extern int hoc_in_yyparse; extern int hoc_intset; - -#endif diff --git a/src/oc/profile.h b/src/oc/profile.h index 457254cd38..1d7db67d1e 100644 --- a/src/oc/profile.h +++ b/src/oc/profile.h @@ -1,5 +1,4 @@ -#ifndef profile_h - +#pragma once extern void start_profile(int); extern void add_profile(int); @@ -10,5 +9,3 @@ extern void add_profile(int); #define PSTART(i) /**/ #define PSTOP(i) /**/ #endif - -#endif diff --git a/src/oc/redef.h b/src/oc/redef.h index 7dcb7f9ea1..526d4b1f6c 100644 --- a/src/oc/redef.h +++ b/src/oc/redef.h @@ -1,7 +1,6 @@ /* /local/src/master/nrn/src/oc/redef.h,v 1.3 1994/10/28 15:18:01 hines Exp */ -#ifndef hoc_redef_h -#define hoc_redef_h +#pragma once #define Break hoc_Break #define Continue hoc_Continue @@ -126,5 +125,3 @@ #define wopen hoc_wopen #define xopen hoc_xopen #define zzdebug hoc_zzdebug - -#endif diff --git a/src/parallel/bbs.h b/src/parallel/bbs.h index b7682b58a6..01f4ed28d0 100644 --- a/src/parallel/bbs.h +++ b/src/parallel/bbs.h @@ -1,5 +1,4 @@ -#ifndef bbs_h -#define bbs_h +#pragma once #include "bbsimpl.h" @@ -73,5 +72,3 @@ class BBS { protected: BBSImpl* impl_; }; - -#endif diff --git a/src/parallel/bbsdirect.h b/src/parallel/bbsdirect.h index d35f859302..b5679dbceb 100644 --- a/src/parallel/bbsdirect.h +++ b/src/parallel/bbsdirect.h @@ -1,5 +1,4 @@ -#ifndef bbsdirect_h -#define bbsdirect_h +#pragma once #include @@ -60,5 +59,3 @@ class BBSDirect: public BBSImpl { bbsmpibuf *sendbuf_, *recvbuf_; #endif }; - -#endif diff --git a/src/parallel/bbsimpl.h b/src/parallel/bbsimpl.h index 3c7806b214..6a89af82ed 100644 --- a/src/parallel/bbsimpl.h +++ b/src/parallel/bbsimpl.h @@ -1,5 +1,4 @@ -#ifndef bbsimpl_h -#define bbsimpl_h +#pragma once class BBSImpl { public: @@ -73,5 +72,3 @@ class BBSImpl { // intracommunicate via the bulletin board but only via // mpi on the subworld communicator. }; - -#endif diff --git a/src/parallel/bbslocal.h b/src/parallel/bbslocal.h index 853ea40c24..920ea557f3 100644 --- a/src/parallel/bbslocal.h +++ b/src/parallel/bbslocal.h @@ -1,5 +1,4 @@ -#ifndef bbslocal_h -#define bbslocal_h +#pragma once #include "bbsimpl.h" @@ -48,5 +47,3 @@ class BBSLocal: public BBSImpl { private: KeepArgs* keepargs_; }; - -#endif diff --git a/src/parallel/bbslsrv.h b/src/parallel/bbslsrv.h index 61fea6d797..0e7a866a5b 100644 --- a/src/parallel/bbslsrv.h +++ b/src/parallel/bbslsrv.h @@ -1,5 +1,4 @@ -#ifndef bbslsrv_h -#define bbslsrv_h +#pragma once #include @@ -71,5 +70,3 @@ class BBSLocalServer { ResultList* results_; int next_id_; }; - -#endif diff --git a/src/parallel/bbslsrv2.h b/src/parallel/bbslsrv2.h index eb86b29fc2..de9489d74e 100644 --- a/src/parallel/bbslsrv2.h +++ b/src/parallel/bbslsrv2.h @@ -1,5 +1,4 @@ -#ifndef bbslsrv2_h -#define bbslsrv2_h +#pragma once #include @@ -36,5 +35,3 @@ class BBSDirectServer { int context_buf_; int remaining_context_cnt_; }; - -#endif diff --git a/src/parallel/bbsrcli.h b/src/parallel/bbsrcli.h index 05a58a5c96..70bcfa3790 100644 --- a/src/parallel/bbsrcli.h +++ b/src/parallel/bbsrcli.h @@ -1,5 +1,4 @@ -#ifndef bbsrcli_h -#define bbsrcli_h +#pragma once #include #include "bbsimpl.h" @@ -58,5 +57,3 @@ class BBSClient: public BBSImpl { // implemented as PVM Client bbsmpibuf *sendbuf_, *recvbuf_, *request_; #endif }; - -#endif diff --git a/src/parallel/bbssrv.h b/src/parallel/bbssrv.h index 1b2efcd9fd..3a383a0ccb 100644 --- a/src/parallel/bbssrv.h +++ b/src/parallel/bbssrv.h @@ -1,5 +1,4 @@ -#ifndef bbssrv_h -#define bbssrv_h +#pragma once #define QUIT 0 #define POST 1 @@ -21,4 +20,3 @@ #define CRAY_POST_TODO 18 #define CRAY_POST_RESULT 19 #define FIRSTID 20 -#endif diff --git a/src/parallel/bbssrv2mpi.h b/src/parallel/bbssrv2mpi.h index 08944c2574..988c6da8e8 100644 --- a/src/parallel/bbssrv2mpi.h +++ b/src/parallel/bbssrv2mpi.h @@ -1,5 +1,4 @@ -#ifndef bbslsrv2_h -#define bbslsrv2_h +#pragma once #include #include @@ -54,5 +53,3 @@ class BBSDirectServer { bbsmpibuf* context_buf_; int remaining_context_cnt_; }; - -#endif From b72b67da38b221e767cc0852af0d0221cd4dfef4 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Mon, 25 Mar 2024 18:44:49 +0100 Subject: [PATCH 05/62] Downgrade Python 3.8 in CI (#2802) Python 3.8.10 universal2 installer has a deployment target of 11, which is newer than the deployment target we are using for NEURON (10.15), and 3.8.9 supports 10.15. --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4a237d6b43..b7dd958f4a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -90,8 +90,8 @@ stages: matrix: Python38: python.version: '3.8' - python.org.version: '3.8.10' - python.installer.name: 'macos11.pkg' + python.org.version: '3.8.9' + python.installer.name: 'macosx10.9.pkg' Python39: python.version: '3.9' python.org.version: '3.9.13' From 8d03f05acf46fb59084cecd8a63bff41eec2a38f Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 26 Mar 2024 06:29:30 +0700 Subject: [PATCH 06/62] Use instead of deprecated . (#2799) --- cmake/ConfigFileSetting.cmake | 1 - cmake_nrnconf.h.in | 3 -- docs/hoc/programming/system.rst | 3 +- docs/python/programming/system.rst | 3 +- src/coreneuron/utils/utils.cpp | 8 ++-- src/nrnoc/multicore.cpp | 1 - src/oc/ftime.cpp | 77 ++++++++---------------------- src/oc/hoc.cpp | 26 ---------- 8 files changed, 25 insertions(+), 97 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 668ea44548..cae5c0fa97 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -138,7 +138,6 @@ check_include_files("dlfcn.h;stdint.h;stddef.h;inttypes.h;stdlib.h;strings.h;str # NRN_HEADERS_INCLUDE_LIST is second argument (headers) is empty. nrn_check_symbol_exists("bcopy" "strings.h" HAVE_BCOPY) nrn_check_symbol_exists("bzero" "strings.h" HAVE_BZERO) -nrn_check_symbol_exists("gettimeofday" "sys/time.h" HAVE_GETTIMEOFDAY) nrn_check_symbol_exists("index" "strings.h" HAVE_INDEX) nrn_check_symbol_exists("isatty" "unistd.h" HAVE_ISATTY) nrn_check_symbol_exists("iv" "" HAVE_IV) diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index c70ddbfa85..f07a76f8ad 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -37,9 +37,6 @@ /* Define to 1 if you have the `feenableexcept' function. */ #undef HAVE_FEENABLEEXCEPT -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - /* Define to 1 if you have the `index' function. */ #undef HAVE_INDEX diff --git a/docs/hoc/programming/system.rst b/docs/hoc/programming/system.rst index ea8b225432..e10a75bee7 100644 --- a/docs/hoc/programming/system.rst +++ b/docs/hoc/programming/system.rst @@ -220,8 +220,7 @@ Timing .. hoc:function:: startsw - Initializes a stopwatch with a resolution of 1 second or 0.01 second if - gettimeofday system call is available. See :hoc:func:`stopsw` . + Initializes a stopwatch with a resolution of 0.01 second. See :hoc:func:`stopsw`. ---- diff --git a/docs/python/programming/system.rst b/docs/python/programming/system.rst index 7c416a1067..0157ba2135 100755 --- a/docs/python/programming/system.rst +++ b/docs/python/programming/system.rst @@ -251,8 +251,7 @@ Timing ``h.startsw()`` - Initializes a stopwatch with a resolution of 1 second or 0.01 second if - gettimeofday system call is available. See :func:`stopsw` . + Initializes a stopwatch with a resolution of 0.01 second. See :func:`stopsw`. ---- diff --git a/src/coreneuron/utils/utils.cpp b/src/coreneuron/utils/utils.cpp index 533e8dbbea..285682b673 100644 --- a/src/coreneuron/utils/utils.cpp +++ b/src/coreneuron/utils/utils.cpp @@ -5,7 +5,7 @@ # See top-level LICENSE file for details. # =============================================================================. */ -#include +#include #include "utils.hpp" #include "coreneuron/apps/corenrn_parameters.hpp" @@ -26,9 +26,9 @@ double nrn_wtime() { } else #endif { - struct timeval time1; - gettimeofday(&time1, nullptr); - return (time1.tv_sec + time1.tv_usec / 1.e6); + const auto now = std::chrono::time_point_cast>( + std::chrono::system_clock::now()); + return now.time_since_epoch().count(); } } diff --git a/src/nrnoc/multicore.cpp b/src/nrnoc/multicore.cpp index 4f143d3cf0..83c8e3ff05 100644 --- a/src/nrnoc/multicore.cpp +++ b/src/nrnoc/multicore.cpp @@ -60,7 +60,6 @@ void (*nrn_mk_transfer_thread_data_)(); static int busywait_; static int busywait_main_; extern void nrn_thread_error(const char*); -extern double nrn_timeus(); extern void (*nrn_multisplit_setup_)(); extern int v_structure_change; extern int diam_changed; diff --git a/src/oc/ftime.cpp b/src/oc/ftime.cpp index b7d543d4ab..7a6daac9fb 100644 --- a/src/oc/ftime.cpp +++ b/src/oc/ftime.cpp @@ -1,69 +1,30 @@ -#include <../../nrnconf.h> #include "hoc.h" -#if defined(HAVE_GETTIMEOFDAY) - -#include +#include static double start_time = 0.; -#else - -#include -static time_t start_time = 0; /* time_t is a long */ -static time_t stop_time = 1; - -#endif - -#define Ret(a) \ - hoc_ret(); \ - hoc_pushx(a); - -double nrn_time(void) { -#if defined(HAVE_GETTIMEOFDAY) - int ms10; - struct timeval x; - gettimeofday(&x, (struct timezone*) 0); - ms10 = x.tv_usec / 10000; - start_time = (100. * (double) (x.tv_sec) + (double) ms10) / 100.; - return (start_time); -#else - return ((double) time(&start_time)); -#endif +double nrn_time() { + // Get nanoseconds converted in seconds + const auto now = std::chrono::time_point_cast>( + std::chrono::system_clock::now()); + start_time = now.time_since_epoch().count(); + return start_time; } - -void hoc_startsw(void) { - Ret(nrn_time()); +void hoc_startsw() { + hoc_ret(); + hoc_pushx(nrn_time()); } -void hoc_stopsw(void) { -#if defined(HAVE_GETTIMEOFDAY) - double y; - int ms10; - struct timeval x; - gettimeofday(&x, (struct timezone*) 0); - ms10 = x.tv_usec / 10000; - y = (double) (x.tv_sec) + (double) ms10 / 100.; - Ret(y - start_time); - start_time = y; -#else - if (start_time == 0) { - Printf("Must use startsw() first.\n"); - Ret(0.); - } else { - time(&stop_time); - Ret((double) (stop_time - start_time)); - } -#endif +void hoc_stopsw() { + double now = nrn_time(); + hoc_ret(); + hoc_pushx(now - start_time); + start_time = now; } - -double nrn_timeus(void) { -#if defined(HAVE_GETTIMEOFDAY) - struct timeval x; - gettimeofday(&x, (struct timezone*) 0); - return ((double) x.tv_sec + .000001 * ((double) x.tv_usec)); -#else - return 0.; -#endif +double nrn_timeus() { + const auto now = std::chrono::time_point_cast>( + std::chrono::system_clock::now()); + return now.time_since_epoch().count(); } diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index f4542a9586..9dd04faf6e 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -95,35 +95,9 @@ void nrn_feenableexcept() { hoc_pushx((double) result); } -#if 0 -/* performance debugging when gprof is inadequate */ -#include -static unsigned long usec[30]; -static unsigned long oldusec[30]; -static struct timeval tp; -void start_profile(int i){ - gettimeofday(&tp, 0); - oldusec[i] = tp.tv_usec; -} -void add_profile(int i) { - gettimeofday(&tp, 0); - if (tp.tv_usec > oldusec[i]) { - usec[i] += tp.tv_usec - oldusec[i]; - } -} -void pr_profile(void) { - int i; - for (i=0; i < 30; ++i) { - if (usec[i]) { - printf("sec[%d]=%g\n", i, ((double)usec[i])/1000000.); - } - } -} -#else void start_profile(int i) {} void add_profile(int i) {} void pr_profile(void) {} -#endif #if OCSMALL #define READLINE 0 From 8ef62332b87f342fb0f23bb70d776cbae34587d1 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 26 Mar 2024 08:42:29 +0100 Subject: [PATCH 07/62] Remove dead read from a global variable. (#2791) --- src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 124e2d071d..9770e24cbd 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -774,7 +774,6 @@ int nrnthread_dat2_vecplay_inst(int tid, continue; } Memb_list* ml = tml->ml; - int nn = nrn_prop_param_size_[tml->index] * ml->nodecount; auto const legacy_index = ml->legacy_index(pd); if (legacy_index >= 0) { mtype = tml->index; From e6553d7e9d81e7785c876021b937ea830c2cee21 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 26 Mar 2024 08:52:08 +0100 Subject: [PATCH 08/62] Avoid needless `new` and `delete` of `BBSS_*`. (#2790) --- src/nrniv/bbsavestate.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/nrniv/bbsavestate.cpp b/src/nrniv/bbsavestate.cpp index 89b4554256..d342b5a0e2 100644 --- a/src/nrniv/bbsavestate.cpp +++ b/src/nrniv/bbsavestate.cpp @@ -771,10 +771,9 @@ void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size) { BBSaveState* ss = new BBSaveState(); *global_size = 0; if (nrnmpi_myid == 0) { // save global time - BBSS_Cnt* io = new BBSS_Cnt(); - io->d(1, nrn_threads->_t); - *global_size = io->bytecnt(); - delete io; + BBSS_Cnt io{}; + io.d(1, nrn_threads->_t); + *global_size = io.bytecnt(); } *len = ss->counts(gids, sizes); return ss; @@ -782,17 +781,15 @@ void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size) { void bbss_save_global(void* bbss, char* buffer, int sz) { // call only on host 0 usebin_ = 1; - BBSS_IO* io = new BBSS_BufferOut(buffer, sz); - io->d(1, nrn_threads->_t); - delete io; + BBSS_BufferOut io(buffer, sz); + io.d(1, nrn_threads->_t); } void bbss_restore_global(void* bbss, char* buffer, int sz) { // call on all hosts usebin_ = 1; - BBSS_IO* io = new BBSS_BufferIn(buffer, sz); - io->d(1, nrn_threads->_t); + BBSS_BufferIn io(buffer, sz); + io.d(1, nrn_threads->_t); t = nrn_threads->_t; - delete io; bbss_restore_begin(); } void bbss_save(void* bbss, int gid, char* buffer, int sz) { From c66e2b513576261e4b3f782d033092d820411fe5 Mon Sep 17 00:00:00 2001 From: Werner Van Geit Date: Tue, 26 Mar 2024 08:52:58 +0100 Subject: [PATCH 09/62] Mark regular expression as raw string to avoid SyntaxWarning (#2792) --- share/lib/python/neuron/rxd/species.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/lib/python/neuron/rxd/species.py b/share/lib/python/neuron/rxd/species.py index b17577c145..c357f5a9c6 100644 --- a/share/lib/python/neuron/rxd/species.py +++ b/share/lib/python/neuron/rxd/species.py @@ -204,7 +204,7 @@ def _1d_submatrix_n(): _ontology_id = re.compile( - "^\[[a-zA-Z][a-zA-Z0-9_]*:[a-zA-Z0-9_]*\]|[a-zA-Z][a-zA-Z0-9_]*:[a-zA-Z0-9_]*$" + r"^\[[a-zA-Z][a-zA-Z0-9_]*:[a-zA-Z0-9_]*\]|[a-zA-Z][a-zA-Z0-9_]*:[a-zA-Z0-9_]*$" ) From 05b949d4effd4c113c159a2fdc7106611f7166c9 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 26 Mar 2024 20:00:12 +0100 Subject: [PATCH 10/62] Use cfenv instead of fenv.h (#2804) cfenv is part of standard since C++11 --- cmake/ConfigFileSetting.cmake | 3 --- cmake_nrnconf.h.in | 15 --------------- src/ivoc/mymath.cpp | 13 +++---------- src/oc/hoc.cpp | 16 +++------------- 4 files changed, 6 insertions(+), 41 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index cae5c0fa97..d0b458222a 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -119,7 +119,6 @@ set(SUNDIALS_USE_GENERIC_MATH 1) # ============================================================================= nrn_check_include_files(dlfcn.h HAVE_DLFCN_H) nrn_check_include_files(execinfo.h HAVE_EXECINFO_H) -nrn_check_include_files(fenv.h HAVE_FENV_H) nrn_check_include_files(malloc.h HAVE_MALLOC_H) nrn_check_include_files(strings.h HAVE_STRINGS_H) nrn_check_include_files(sys/types.h HAVE_SYS_TYPES_H) @@ -152,8 +151,6 @@ nrn_check_symbol_exists("sigaction" "signal.h" HAVE_SIGACTION) nrn_check_symbol_exists("sigprocmask" "signal.h" HAVE_SIGPROCMASK) nrn_check_symbol_exists("SIGBUS" "signal.h" HAVE_SIGBUS) nrn_check_symbol_exists("stty" "" HAVE_STTY) -nrn_check_cxx_symbol_exists("fesetround" "fenv.h" HAVE_FESETROUND) -nrn_check_cxx_symbol_exists("feenableexcept" "fenv.h" HAVE_FEENABLEEXCEPT) # ============================================================================= # Check data types diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index f07a76f8ad..57436d1977 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -16,27 +16,12 @@ /* if mac os x */ #undef DARWIN -/* Define to 1 if you have the `bcopy' function. */ -#undef HAVE_BCOPY - -/* Define to 1 if you have the `bzero' function. */ -#undef HAVE_BZERO - /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H -/* Define to 1 if you have the header file. */ -#undef HAVE_FENV_H - -/* Define to 1 if you have the `fesetround' function. */ -#undef HAVE_FESETROUND - -/* Define to 1 if you have the `feenableexcept' function. */ -#undef HAVE_FEENABLEEXCEPT - /* Define to 1 if you have the `index' function. */ #undef HAVE_INDEX diff --git a/src/ivoc/mymath.cpp b/src/ivoc/mymath.cpp index 963e7bf711..c0083411e4 100644 --- a/src/ivoc/mymath.cpp +++ b/src/ivoc/mymath.cpp @@ -5,6 +5,7 @@ #include "oc2iv.h" #include #include +#include extern int hoc_return_type_code; @@ -26,14 +27,9 @@ static double inside(void*) { int nrn_feround(int); // return last rounding mode and set to given mode if 1,2,3,4. // order is FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD -#if defined(HAVE_FENV_H) && defined(HAVE_FESETROUND) -#include static int round_mode[] = {FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD}; -#endif int nrn_feround(int mode) { -#if defined(HAVE_FENV_H) && defined(HAVE_FESETROUND) - int oldmode = fegetround(); - int m; + int oldmode = std::fegetround(); if (oldmode == FE_TONEAREST) { oldmode = 2; } else if (oldmode == FE_TOWARDZERO) { @@ -46,12 +42,9 @@ int nrn_feround(int mode) { assert(0); } if (mode > 0 && mode < 5) { - nrn_assert(fesetround(round_mode[mode - 1]) == 0); + nrn_assert(std::fesetround(round_mode[mode - 1]) == 0); } return oldmode; -#else - return 0; -#endif } static double feround(void*) { diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 9dd04faf6e..878f29b963 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -20,6 +20,7 @@ #include "nrnfilewrap.h" #include "../nrniv/backtrace_utils.h" +#include #include #include #include @@ -48,21 +49,11 @@ int (*p_nrnpy_pyrun)(const char* fname); extern int stdin_event_ready(); #endif -#if HAVE_FEENABLEEXCEPT -#define NRN_FLOAT_EXCEPTION 1 -#else -#define NRN_FLOAT_EXCEPTION 0 -#endif - -#if NRN_FLOAT_EXCEPTION -#if !defined(__USE_GNU) -#define __USE_GNU -#endif -#include #define FEEXCEPT (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) static void matherr1(void) { + const int e = std::fetestexcept(FEEXCEPT); /* above gives the signal but for some reason fegetexcept returns 0 */ - switch (fegetexcept()) { + switch (e) { case FE_DIVBYZERO: fprintf(stderr, "Floating exception: Divide by zero\n"); break; @@ -74,7 +65,6 @@ static void matherr1(void) { break; } } -#endif int nrn_mpiabort_on_error_{1}; From 8c1473babdf8fa529b8531160b3d7cfac70fb29d Mon Sep 17 00:00:00 2001 From: Weina Ji Date: Wed, 27 Mar 2024 13:10:32 +0100 Subject: [PATCH 11/62] Set MPI barrier at the end of coreneuron model writing to avoid race condition (#2796) In the case of filemode with CoreNEURON, `rank 0` may not have finished writing `bbcore_mech.dat` and `globals.dat` on the neuron side but other ranks might try to read those on the coreneuron side. As part of this PR, we make sure the neuron has finished writing files before we call CoreNEURON. --- src/nrniv/nrncore_write.cpp | 5 +++++ test/coreneuron/test_spikes.py | 10 ++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/nrniv/nrncore_write.cpp b/src/nrniv/nrncore_write.cpp index 29d6bdc978..7b0859e3d2 100644 --- a/src/nrniv/nrncore_write.cpp +++ b/src/nrniv/nrncore_write.cpp @@ -415,6 +415,11 @@ int nrncore_psolve(double tstop, int file_mode) { CORENRN_DATA_DIR = find_datpath_in_arguments(args); } write_corenrn_model(CORENRN_DATA_DIR); +#if NRNMPI + if (nrnmpi_numprocs > 1) { + nrnmpi_barrier(); + } +#endif } nrncore_run(args); // data return nt._t so copy to t diff --git a/test/coreneuron/test_spikes.py b/test/coreneuron/test_spikes.py index dc2185c804..6522774648 100644 --- a/test/coreneuron/test_spikes.py +++ b/test/coreneuron/test_spikes.py @@ -1,6 +1,5 @@ from neuron.tests.utils.strtobool import strtobool import os -import tempfile # Hacky, but it's non-trivial to pass commandline arguments to pytest tests. enable_gpu = bool(strtobool(os.environ.get("CORENRN_ENABLE_GPU", "false"))) @@ -123,13 +122,12 @@ def run(mode): run_modes = [0] if file_mode else [0, 1, 2] for mode in run_modes: run(mode) - # Make sure that file mode also works with custom coreneuron.data_path + # Make sure that file mode also works with custom coreneuron.model_path if file_mode: - temp_coreneuron_data_folder = tempfile.TemporaryDirectory( - "coreneuron_input" - ) # auto removed - coreneuron.data_path = temp_coreneuron_data_folder.name + coreneuron.model_path = "coreneuron_input" run(0) + # revert setting for the following coreneuron runs + coreneuron._model_path = None return h From cd658719e0ff250e87963544883115fce2d5e10b Mon Sep 17 00:00:00 2001 From: JCGoran Date: Thu, 28 Mar 2024 17:14:43 +0100 Subject: [PATCH 12/62] Remove popup of Finder when installing on MacOS (#2805) --- src/mac/activate-apps-cmake.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mac/activate-apps-cmake.sh b/src/mac/activate-apps-cmake.sh index 84125501cb..47c1cddf7a 100755 --- a/src/mac/activate-apps-cmake.sh +++ b/src/mac/activate-apps-cmake.sh @@ -57,13 +57,6 @@ done echo "$lst" -osascript -e 'tell application "Finder"'\ - -e 'activate'\ - -e 'make new Finder window'\ - -e 'set target of Finder window 1 to folder '"$lst"' of startup disk'\ - -e 'set target of Finder window 1 to folder "bin" of folder '"$lst"' of startup disk'\ - -e 'end tell' - # force rebuild of the neurondemo (perhaps as universal2) DEMO="${NRN_INSTALL}/share/nrn/demo" rm -f -r ${DEMO}/neuron ${DEMO}/release/${CPU} From b4935af4818fe671b233a9c725974091642af442 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 28 Mar 2024 22:29:05 +0100 Subject: [PATCH 13/62] Move to Catch2 v3 (#2809) --- CMakeLists.txt | 2 +- external/catch2 | 2 +- test/benchmarks/threads/test_multicore.cpp | 4 ++- test/common/catch2_main.cpp | 7 +++--- test/coreneuron/unit/alignment/CMakeLists.txt | 2 +- test/coreneuron/unit/alignment/alignment.cpp | 4 +-- .../unit/cmdline_interface/CMakeLists.txt | 2 +- .../test_cmdline_interface.cpp | 3 +-- .../unit/interleave_info/CMakeLists.txt | 2 +- .../interleave_info/check_constructors.cpp | 3 +-- test/coreneuron/unit/lfp/CMakeLists.txt | 2 +- test/coreneuron/unit/lfp/lfp.cpp | 17 +++++++------ test/coreneuron/unit/queueing/CMakeLists.txt | 2 +- .../unit/queueing/test_queueing.cpp | 3 +-- test/coreneuron/unit/solver/CMakeLists.txt | 2 +- test/coreneuron/unit/solver/test_solver.cpp | 8 +++--- test/cover/unit_tests/cover.cpp | 2 +- test/unit_tests/basic.cpp | 2 +- test/unit_tests/container/container.cpp | 2 +- .../container/generic_data_handle.cpp | 2 +- test/unit_tests/container/mechanism.cpp | 4 ++- test/unit_tests/container/node.cpp | 5 +++- test/unit_tests/iovec.cpp | 3 ++- test/unit_tests/matrix.cpp | 2 +- test/unit_tests/oc/hoc_interpreter.cpp | 25 +++++++++++-------- test/unit_tests/utils/enumerate.cpp | 2 +- 26 files changed, 62 insertions(+), 52 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85dc3cd3d6..ef953d55ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -805,7 +805,7 @@ if(NRN_ENABLE_TESTS) if(NOT TARGET Catch2::Catch2) nrn_add_external_project(catch2) set(CATCH_DIR ${PROJECT_SOURCE_DIR}/external/catch2) - list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/external/catch2/contrib) + list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/external/catch2/extras) include(Catch) endif() include(CTest) diff --git a/external/catch2 b/external/catch2 index c4e3767e26..8ac8190e49 160000 --- a/external/catch2 +++ b/external/catch2 @@ -1 +1 @@ -Subproject commit c4e3767e265808590986d5db6ca1b5532a7f3d13 +Subproject commit 8ac8190e494a381072c89f5e161b92a08d98b37b diff --git a/test/benchmarks/threads/test_multicore.cpp b/test/benchmarks/threads/test_multicore.cpp index ca1288c148..5fe1ef2d26 100644 --- a/test/benchmarks/threads/test_multicore.cpp +++ b/test/benchmarks/threads/test_multicore.cpp @@ -6,10 +6,12 @@ #include "nrn_ansi.h" #include "ocfunc.h" -#include +#include +#include #include #include +#include #include /* @brief diff --git a/test/common/catch2_main.cpp b/test/common/catch2_main.cpp index 09f9a7a715..7c840716a9 100644 --- a/test/common/catch2_main.cpp +++ b/test/common/catch2_main.cpp @@ -1,6 +1,5 @@ -// Has to be included early to stop NEURON's macros wreaking havoc -#define CATCH_CONFIG_RUNNER -#include +#include +#include #include "code.h" #include "neuron.h" @@ -55,7 +54,7 @@ int main(int argc, char* argv[]) { Catch::Session session{}; - using namespace Catch::clara; + using namespace Catch::Clara; auto cli = session.cli() | Opt(nrn::test::PROCESSORS, "number of PROCESSORS to consider")["--processors"]( "How many processors are available for perf tests"); diff --git a/test/coreneuron/unit/alignment/CMakeLists.txt b/test/coreneuron/unit/alignment/CMakeLists.txt index bf821b9d20..1df4843ee2 100644 --- a/test/coreneuron/unit/alignment/CMakeLists.txt +++ b/test/coreneuron/unit/alignment/CMakeLists.txt @@ -4,6 +4,6 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(alignment_test_bin alignment.cpp) -target_link_libraries(alignment_test_bin coreneuron-unit-test Catch2::Catch2) +target_link_libraries(alignment_test_bin coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME alignment_test COMMAND $) cpp_cc_configure_sanitizers(TARGET alignment_test_bin TEST alignment_test) diff --git a/test/coreneuron/unit/alignment/alignment.cpp b/test/coreneuron/unit/alignment/alignment.cpp index 9a7b5ebadf..ab2f6f7d2a 100644 --- a/test/coreneuron/unit/alignment/alignment.cpp +++ b/test/coreneuron/unit/alignment/alignment.cpp @@ -7,8 +7,8 @@ */ #include "coreneuron/utils/memory.h" -#define CATCH_CONFIG_MAIN -#include +#include +#include #include #include diff --git a/test/coreneuron/unit/cmdline_interface/CMakeLists.txt b/test/coreneuron/unit/cmdline_interface/CMakeLists.txt index c2448d4e7b..1b7fdc16aa 100644 --- a/test/coreneuron/unit/cmdline_interface/CMakeLists.txt +++ b/test/coreneuron/unit/cmdline_interface/CMakeLists.txt @@ -4,6 +4,6 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(cmd_interface_test_bin test_cmdline_interface.cpp) -target_link_libraries(cmd_interface_test_bin coreneuron-unit-test Catch2::Catch2) +target_link_libraries(cmd_interface_test_bin coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME cmd_interface_test COMMAND $) cpp_cc_configure_sanitizers(TARGET cmd_interface_test_bin TEST cmd_interface_test) diff --git a/test/coreneuron/unit/cmdline_interface/test_cmdline_interface.cpp b/test/coreneuron/unit/cmdline_interface/test_cmdline_interface.cpp index bd5e94bf66..f352c6c9f3 100644 --- a/test/coreneuron/unit/cmdline_interface/test_cmdline_interface.cpp +++ b/test/coreneuron/unit/cmdline_interface/test_cmdline_interface.cpp @@ -7,8 +7,7 @@ */ #include "coreneuron/apps/corenrn_parameters.hpp" -#define CATCH_CONFIG_MAIN -#include +#include #include diff --git a/test/coreneuron/unit/interleave_info/CMakeLists.txt b/test/coreneuron/unit/interleave_info/CMakeLists.txt index 5e16d0760a..47d4d59f51 100644 --- a/test/coreneuron/unit/interleave_info/CMakeLists.txt +++ b/test/coreneuron/unit/interleave_info/CMakeLists.txt @@ -4,6 +4,6 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(interleave_info_bin check_constructors.cpp) -target_link_libraries(interleave_info_bin coreneuron-unit-test Catch2::Catch2) +target_link_libraries(interleave_info_bin coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME interleave_info_constructor_test COMMAND $) cpp_cc_configure_sanitizers(TARGET interleave_info_bin TEST interleave_info_constructor_test) diff --git a/test/coreneuron/unit/interleave_info/check_constructors.cpp b/test/coreneuron/unit/interleave_info/check_constructors.cpp index d780f772a4..994021b003 100644 --- a/test/coreneuron/unit/interleave_info/check_constructors.cpp +++ b/test/coreneuron/unit/interleave_info/check_constructors.cpp @@ -7,8 +7,7 @@ */ #include "coreneuron/permute/cellorder.hpp" -#define CATCH_CONFIG_MAIN -#include +#include #include using namespace coreneuron; diff --git a/test/coreneuron/unit/lfp/CMakeLists.txt b/test/coreneuron/unit/lfp/CMakeLists.txt index 56600060b5..76c701cd02 100644 --- a/test/coreneuron/unit/lfp/CMakeLists.txt +++ b/test/coreneuron/unit/lfp/CMakeLists.txt @@ -4,7 +4,7 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(lfp_test_bin lfp.cpp) -target_link_libraries(lfp_test_bin coreneuron-unit-test Catch2::Catch2) +target_link_libraries(lfp_test_bin coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME lfp_test COMMAND $) cpp_cc_configure_sanitizers(TARGET lfp_test_bin TEST lfp_test) set_property( diff --git a/test/coreneuron/unit/lfp/lfp.cpp b/test/coreneuron/unit/lfp/lfp.cpp index 24d60cf3ec..673116595f 100644 --- a/test/coreneuron/unit/lfp/lfp.cpp +++ b/test/coreneuron/unit/lfp/lfp.cpp @@ -10,8 +10,8 @@ #include "coreneuron/io/reports/report_event.hpp" #include "coreneuron/mpi/nrnmpi.h" -#define CATCH_CONFIG_MAIN -#include +#include +#include #include @@ -74,7 +74,9 @@ TEST_CASE("LFP_PointSource_LineSource") { // TEST of analytic vs numerical integration std::clog << "ANALYTIC line source " << analytic_circling_lfp << " vs NUMERIC line source LFP " << numeric_circling_lfp << "\n"; - REQUIRE(Approx(analytic_circling_lfp).margin(1.0e-6) == numeric_circling_lfp); + REQUIRE_THAT(analytic_circling_lfp, + Catch::Matchers::WithinRel(numeric_circling_lfp, + std::numeric_limits::epsilon() * 100.)); // TEST of LFP Flooring if (approaching_elec[1] < 0.866e-6) { REQUIRE(analytic_approaching_lfp == 1.0e6); @@ -104,8 +106,8 @@ TEST_CASE("LFP_PointSource_LineSource") { segments_starts, segments_ends, radii, indices, electrodes, 1.0); lfpp.template lfp>({0.0, 1.0, 2.0, 3.0}); std::vector res_point_source = lfpp.lfp_values(); - REQUIRE(res_line_source[0] == Approx(res_point_source[0]).margin(1.0)); - REQUIRE(res_line_source[1] == Approx(res_point_source[1]).margin(1.0)); + REQUIRE_THAT(res_line_source[0], Catch::Matchers::WithinAbs(res_point_source[0], 1.0)); + REQUIRE_THAT(res_line_source[1], Catch::Matchers::WithinAbs(res_point_source[1], 1.0)); #if NRNMPI nrnmpi_finalize(); #endif @@ -113,7 +115,6 @@ TEST_CASE("LFP_PointSource_LineSource") { #ifdef ENABLE_SONATA_REPORTS #define CATCH_CONFIG_MAIN -#include TEST_CASE("LFP_ReportEvent") { const std::string report_name = "compartment_report"; @@ -179,8 +180,8 @@ TEST_CASE("LFP_ReportEvent") { ReportEvent event(dt, tstart, vars_to_report, report_name.data(), report_dt, report_type); event.lfp_calc(&nt); - REQUIRE(mapinfo->_lfp[0] == Approx(5.5).margin(1.0)); - REQUIRE(mapinfo->_lfp[3] == Approx(7.0).margin(1.0)); + REQUIRE_THAT(mapinfo->_lfp[0], Catch::Matchers::WithinAbs(5.5, 1.0)); + REQUIRE_THAT(mapinfo->_lfp[3], Catch::Matchers::WithinAbs(7.0, 1.0)); delete mapinfo; delete nt.nrn_fast_imem; diff --git a/test/coreneuron/unit/queueing/CMakeLists.txt b/test/coreneuron/unit/queueing/CMakeLists.txt index 08250a479b..d01e51dcab 100644 --- a/test/coreneuron/unit/queueing/CMakeLists.txt +++ b/test/coreneuron/unit/queueing/CMakeLists.txt @@ -4,6 +4,6 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(queuing_test_bin test_queueing.cpp) -target_link_libraries(queuing_test_bin coreneuron-unit-test Catch2::Catch2) +target_link_libraries(queuing_test_bin coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME queuing_test COMMAND $) cpp_cc_configure_sanitizers(TARGET queuing_test_bin TEST queuing_test) diff --git a/test/coreneuron/unit/queueing/test_queueing.cpp b/test/coreneuron/unit/queueing/test_queueing.cpp index 6f6ef6739a..1b240a9cc2 100644 --- a/test/coreneuron/unit/queueing/test_queueing.cpp +++ b/test/coreneuron/unit/queueing/test_queueing.cpp @@ -8,8 +8,7 @@ #include "coreneuron/network/netcvode.hpp" #include "coreneuron/network/tqueue.hpp" -#define CATCH_CONFIG_MAIN -#include +#include #include #include diff --git a/test/coreneuron/unit/solver/CMakeLists.txt b/test/coreneuron/unit/solver/CMakeLists.txt index 74af549094..98bbdfee6c 100644 --- a/test/coreneuron/unit/solver/CMakeLists.txt +++ b/test/coreneuron/unit/solver/CMakeLists.txt @@ -4,6 +4,6 @@ # See top-level LICENSE file for details. # ============================================================================= add_executable(test-solver test_solver.cpp) -target_link_libraries(test-solver coreneuron-unit-test Catch2::Catch2) +target_link_libraries(test-solver coreneuron-unit-test Catch2::Catch2WithMain) add_test(NAME test-solver COMMAND $) cpp_cc_configure_sanitizers(TARGET test-solver TEST test-solver) diff --git a/test/coreneuron/unit/solver/test_solver.cpp b/test/coreneuron/unit/solver/test_solver.cpp index dcdd93d6f7..cce70d0f33 100644 --- a/test/coreneuron/unit/solver/test_solver.cpp +++ b/test/coreneuron/unit/solver/test_solver.cpp @@ -11,8 +11,8 @@ #include "coreneuron/permute/node_permute.h" #include "coreneuron/sim/multicore.hpp" -#define CATCH_CONFIG_MAIN -#include +#include +#include #include #include @@ -295,9 +295,9 @@ void compare_solver_data( REQUIRE(impl_data[n_thread].parent_index.size() == ref_data[n_thread].parent_index.size()); REQUIRE(impl_data[n_thread].rhs.size() == ref_data[n_thread].rhs.size()); - CHECK_THAT(impl_data[n_thread].d, Catch::Approx(ref_data[n_thread].d)); + CHECK_THAT(impl_data[n_thread].d, Catch::Matchers::Approx(ref_data[n_thread].d)); REQUIRE(impl_data[n_thread].parent_index == ref_data[n_thread].parent_index); - CHECK_THAT(impl_data[n_thread].rhs, Catch::Approx(ref_data[n_thread].rhs)); + CHECK_THAT(impl_data[n_thread].rhs, Catch::Matchers::Approx(ref_data[n_thread].rhs)); } } } diff --git a/test/cover/unit_tests/cover.cpp b/test/cover/unit_tests/cover.cpp index c1c2945b57..ca2a5a9a8e 100644 --- a/test/cover/unit_tests/cover.cpp +++ b/test/cover/unit_tests/cover.cpp @@ -3,7 +3,7 @@ extern bool hoc_valid_stmt(const char*, Object*); -#include +#include // Help cover PR's diff --git a/test/unit_tests/basic.cpp b/test/unit_tests/basic.cpp index 2ca0e4cad5..dce950f188 100644 --- a/test/unit_tests/basic.cpp +++ b/test/unit_tests/basic.cpp @@ -7,7 +7,7 @@ #include "ivoc.h" #endif -#include +#include SCENARIO("Test fast_imem calculation", "[Neuron][fast_imem]") { GIVEN("A section") { diff --git a/test/unit_tests/container/container.cpp b/test/unit_tests/container/container.cpp index 4ebadf1624..37be37b803 100644 --- a/test/unit_tests/container/container.cpp +++ b/test/unit_tests/container/container.cpp @@ -3,7 +3,7 @@ #include "neuron/model_data.hpp" #include "nrn_ansi.h" -#include +#include #include diff --git a/test/unit_tests/container/generic_data_handle.cpp b/test/unit_tests/container/generic_data_handle.cpp index 2a24ae5684..50fe16496d 100644 --- a/test/unit_tests/container/generic_data_handle.cpp +++ b/test/unit_tests/container/generic_data_handle.cpp @@ -2,7 +2,7 @@ #include "neuron/container/node.hpp" #include "neuron/model_data.hpp" -#include +#include #include #include diff --git a/test/unit_tests/container/mechanism.cpp b/test/unit_tests/container/mechanism.cpp index 0ead73d2c2..9166158ecc 100644 --- a/test/unit_tests/container/mechanism.cpp +++ b/test/unit_tests/container/mechanism.cpp @@ -3,11 +3,13 @@ #include "neuron/container/soa_container.hpp" #include "neuron/model_data.hpp" -#include +#include #include #include +#include #include +#include #include #include diff --git a/test/unit_tests/container/node.cpp b/test/unit_tests/container/node.cpp index 263db0c51a..0e8298f269 100644 --- a/test/unit_tests/container/node.cpp +++ b/test/unit_tests/container/node.cpp @@ -2,10 +2,13 @@ #include "neuron/container/soa_container.hpp" #include "section.h" -#include +#include +#include #include +#include #include +#include #include #include #include diff --git a/test/unit_tests/iovec.cpp b/test/unit_tests/iovec.cpp index 946ad7c7fa..64757933ca 100644 --- a/test/unit_tests/iovec.cpp +++ b/test/unit_tests/iovec.cpp @@ -1,9 +1,10 @@ #include +#include #include #include "oc_ansi.h" -#include +#include // This function is the one that is used in all nrn-modeldb-ci // Keep as is diff --git a/test/unit_tests/matrix.cpp b/test/unit_tests/matrix.cpp index 52f2b88abd..27386501ca 100644 --- a/test/unit_tests/matrix.cpp +++ b/test/unit_tests/matrix.cpp @@ -3,7 +3,7 @@ #include #include "ivocvect.h" -#include +#include using namespace Catch::literals; template diff --git a/test/unit_tests/oc/hoc_interpreter.cpp b/test/unit_tests/oc/hoc_interpreter.cpp index eb3a66b997..36f03aaaea 100644 --- a/test/unit_tests/oc/hoc_interpreter.cpp +++ b/test/unit_tests/oc/hoc_interpreter.cpp @@ -1,4 +1,6 @@ -#include +#include +#include +#include #include "classreg.h" #include "code.h" @@ -135,7 +137,7 @@ std::string hoc_oc_require_error(const char* buf) { return output; } -using Catch::Matchers::Contains; // ContainsSubstring in newer Catch2 +using Catch::Matchers::ContainsSubstring; SCENARIO("Test calling code from HOC that throws exceptions", "[NEURON][hoc_interpreter]") { static bool registered = false; if (!registered) { @@ -152,15 +154,17 @@ SCENARIO("Test calling code from HOC that throws exceptions", "[NEURON][hoc_inte } GIVEN("A HOC object constructor that throws") { REQUIRE_THAT(hoc_oc_require_error("util = new UtilityThatLikesThrowing()\n"), - Contains("hoc_execerror: UtilityThatLikesThrowing[0] constructor: need at " - "least one argument")); + ContainsSubstring( + "hoc_execerror: UtilityThatLikesThrowing[0] constructor: need at " + "least one argument")); } GIVEN("A HOC object destructor that throws") { REQUIRE_THAT(hoc_oc_require_error("util = nil\n" "util = new UtilityThatLikesThrowing(1)\n" "util = nil\n"), - Contains("hoc_execerror: UtilityThatLikesThrowing[0] destructor: throwing " - "from HOC destructor")); + ContainsSubstring( + "hoc_execerror: UtilityThatLikesThrowing[0] destructor: throwing " + "from HOC destructor")); } GIVEN("A HOC object whose constructor and destructor succeed") { // Make sure there are not any instances alive from previous tests, otherwise we can't @@ -173,14 +177,15 @@ SCENARIO("Test calling code from HOC that throws exceptions", "[NEURON][hoc_inte WHEN("A member function that throws is called") { REQUIRE_THAT( hoc_oc_require_error(("util.throw_error" + method_suffix + "()\n").c_str()), - Contains("hoc_execerror: UtilityThatLikesThrowing[0]::throw_error" + method_suffix + - ": throwing " - "from throw_error")); + ContainsSubstring("hoc_execerror: UtilityThatLikesThrowing[0]::throw_error" + + method_suffix + + ": throwing " + "from throw_error")); } WHEN("A member function that calls hoc_execerror is called") { REQUIRE_THAT(hoc_oc_require_error( ("util.call_execerror" + method_suffix + "()\n").c_str()), - Contains("hoc_execerror: throwing a tantrum")); + ContainsSubstring("hoc_execerror: throwing a tantrum")); } } } diff --git a/test/unit_tests/utils/enumerate.cpp b/test/unit_tests/utils/enumerate.cpp index 2ef2dd00bf..691dc179fb 100644 --- a/test/unit_tests/utils/enumerate.cpp +++ b/test/unit_tests/utils/enumerate.cpp @@ -2,7 +2,7 @@ #include "utils/enumerate.h" -#include +#include TEST_CASE("apply_to_first", "[Neuron]") { From 004ba5922a0b637a0f2aabed61d400b454fed817 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Tue, 2 Apr 2024 13:34:54 +0200 Subject: [PATCH 14/62] Update install instructions (#2772) --- docs/install/install_instructions.md | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index 7c154c20f2..9f2da7e534 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -211,11 +211,6 @@ The following packages are optional (see build options): - MPI (for parallel) - X11 (Linux) or XQuartz (MacOS) (for GUI) -Note that you may have to force Cython version: -```bash -pip install "cython<3" -``` - Depending on platform you can install these dependencies as follows: @@ -226,21 +221,28 @@ The easiest way to install dependencies on Mac OS is to use [brew](https://brew. once [brew is installed](https://docs.brew.sh/Installation) you can do: ```bash -brew install coreutils openmpi cmake +brew install coreutils openmpi cmake flex bison brew install --cask xquartz ``` Once these packages are installed, setup PATH as: ```bash -export PATH=/usr/local/bin/:$PATH +export PATH="/usr/local/bin:/usr/local/opt/bison/bin:/usr/local/opt/flex/bin:$PATH" ``` If the desired python version is not installed, you can install it using -[official distribution](https://www.python.org/downloads/macos/). Also, note that +[official distribution](https://www.python.org/downloads/macos/) or via brew. Also, note that [Xcode Command Line Tools](https://stackoverflow.com/questions/9329243/how-to-install-xcode-command-line-tools) needs to be installed for development. +Finally, if you are building NEURON with the Python interface, you need to install all of the Python dependencies: + +```bash +pip3 install --user --upgrade pip +pip3 install --user -r nrn_requirements.txt +``` + #### Mac OS - Apple M1 @@ -267,21 +269,18 @@ needs to be installed for development. echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> $HOME/.zprofile eval $(/opt/homebrew/bin/brew shellenv) - brew install cmake - brew install open-mpi + brew install open-mpi cmake flex bison pip3 install --user --upgrade pip - export PATH="$HOME/Library/Python/3.8/bin":$PATH - pip3 install --user cython + pip3 install --user -r nrn_requirements.txt ``` Once these packages are installed, setup PATH as: ```bash -export PATH=/opt/homebrew/opt/bison/bin/:/opt/homebrew/opt/flex/bin/:/opt/homebrew/bin/:$PATH +export PATH="/opt/homebrew/opt/bison/bin/:/opt/homebrew/opt/flex/bin/:/opt/homebrew/bin/:$PATH" ``` - #### Linux Depending on the platform (Ubuntu, CentOS, Fedora, Debian, Red Hat etc.), there are different ways to @@ -293,7 +292,7 @@ sudo apt-get install -y bison cmake flex git \ libncurses-dev libopenmpi-dev libx11-dev \ libxcomposite-dev openmpi-bin python3-dev # for python dependencies -pip install scipy numpy cython +pip install -r nrn_requirements.txt ``` We recommend using platform specific instructions provided in [nrn-build-ci](https://github.com/neuronsimulator/nrn-build-ci#scheduled-ci-builds-for-neuron) repository. From f36699066006089f3de40366ba6bea18d85c629e Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 3 Apr 2024 01:29:16 +0200 Subject: [PATCH 15/62] Remove check for deprecated header (#2813) --- cmake/ConfigFileSetting.cmake | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index d0b458222a..a6bde94287 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -166,11 +166,6 @@ nrn_check_type_exists(sys/types.h uid_t int uid_t) # ============================================================================= nrn_check_signal_return_type(RETSIGTYPE) -# ============================================================================= -# Check direcotry manipulation header -# ============================================================================= -nrn_check_dir_exists(sys/ndir.h HAVE_SYS_NDIR_H) - # ============================================================================= # Copy cmake specific template files # ============================================================================= From d71a336082c0cec8e809f4276e8fab9131f5c8aa Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 5 Apr 2024 09:25:24 +0200 Subject: [PATCH 16/62] Refactor `DatumIndices` (#2798) The names of the members `ion_{type,index}` were confusing and have been renamed. --- .../nrncore_write/callbacks/nrncore_callbacks.cpp | 9 ++++----- src/nrniv/nrncore_write/data/cell_group.cpp | 8 ++++---- src/nrniv/nrncore_write/data/datum_indices.cpp | 11 ++--------- src/nrniv/nrncore_write/data/datum_indices.h | 14 ++++++++++---- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 9770e24cbd..1c2e7bcfa1 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -632,16 +632,15 @@ int* datum2int(int type, int ioff = i * sz; for (int j = 0; j < sz; ++j) { int jj = ioff + j; - int etype = di.ion_type[jj]; - int eindex = di.ion_index[jj]; + int etype = di.datum_type[jj]; + int eindex = di.datum_index[jj]; const int seman = semantics[j]; // Would probably be more clear if use seman for as many as // possible of the cases // below and within each case deal with etype appropriately. - // ion_type and ion_index have become misnomers as they no longer - // refer to ions specificially but the mechanism type where the + // datum_type and datum_index refer to mechanism type where the // range variable lives (and otherwise is generally the same as - // seman). And ion_index refers to the index of the range variable + // seman). And datum_index refers to the index of the range variable // within the mechanism (or voltage, area, etc.) if (seman == -5) { // POINTER to range variable (e.g. voltage) pdata[jj] = eindex; diff --git a/src/nrniv/nrncore_write/data/cell_group.cpp b/src/nrniv/nrncore_write/data/cell_group.cpp index fe25bc1793..02a277f2ce 100644 --- a/src/nrniv/nrncore_write/data/cell_group.cpp +++ b/src/nrniv/nrncore_write/data/cell_group.cpp @@ -227,8 +227,8 @@ void CellGroup::datumtransform(CellGroup* cgs) { DatumIndices& di = cg.datumindices[i++]; di.type = type; int n = ml->nodecount * sz; - di.ion_type = new int[n]; - di.ion_index = new int[n]; + di.datum_type = new int[n]; + di.datum_index = new int[n]; // fill the indices. // had tointroduce a memb_func[i].dparam_semantics registered by each mod file. datumindex_fill(ith, cg, di, ml); @@ -361,8 +361,8 @@ void CellGroup::datumindex_fill(int ith, CellGroup& cg, DatumIndices& di, Memb_l Sprintf(errmes, "Unknown semantics type %d for dparam item %d of", dmap[j], j); hoc_execerror(errmes, memb_func[di.type].sym->name); } - di.ion_type[offset + j] = etype; - di.ion_index[offset + j] = eindex; + di.datum_type[offset + j] = etype; + di.datum_index[offset + j] = eindex; } } } diff --git a/src/nrniv/nrncore_write/data/datum_indices.cpp b/src/nrniv/nrncore_write/data/datum_indices.cpp index 93f57dd9f4..ea4027c913 100644 --- a/src/nrniv/nrncore_write/data/datum_indices.cpp +++ b/src/nrniv/nrncore_write/data/datum_indices.cpp @@ -1,13 +1,6 @@ #include "datum_indices.h" -DatumIndices::DatumIndices() { - type = -1; - ion_type = ion_index = 0; -} - DatumIndices::~DatumIndices() { - if (ion_type) - delete[] ion_type; - if (ion_index) - delete[] ion_index; + delete[] datum_type; + delete[] datum_index; } diff --git a/src/nrniv/nrncore_write/data/datum_indices.h b/src/nrniv/nrncore_write/data/datum_indices.h index 46df3ba67c..ec369ee19e 100644 --- a/src/nrniv/nrncore_write/data/datum_indices.h +++ b/src/nrniv/nrncore_write/data/datum_indices.h @@ -6,10 +6,16 @@ // NrnThread.NrnThreadMembList.Memb_List.data and pdata etc. class DatumIndices { public: - DatumIndices(); + DatumIndices() = default; virtual ~DatumIndices(); - int type; + + // These are the datum of mechanism `type`. + int type = -1; + + // `datum_index[i]` is the index of datum `i` inside the mechanism + // `datum_type[i]`. + // // ordering as though pdata[i][j] was pdata[0][i*sz+j] - int* ion_type; // negative codes semantics, positive codes mechanism type - int* ion_index; // index of range variable relative to beginning of that type + int* datum_type = nullptr; // negative codes semantics, positive codes mechanism type + int* datum_index = nullptr; // index of range variable relative to beginning of that type }; From 93272630905df25b16f1e336b7000840795b068e Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 5 Apr 2024 09:27:30 +0200 Subject: [PATCH 17/62] Simplify round to next multiple. (#2807) --- src/coreneuron/utils/memory.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/coreneuron/utils/memory.h b/src/coreneuron/utils/memory.h index 81a4ce3006..889049c121 100644 --- a/src/coreneuron/utils/memory.h +++ b/src/coreneuron/utils/memory.h @@ -207,14 +207,11 @@ namespace coreneuron { */ template inline int soa_padded_size(int cnt, int layout) { - int imod = cnt % chunk; - if (layout == Layout::AoS) + if (layout == Layout::AoS) { return cnt; - if (imod) { - int idiv = cnt / chunk; - return (idiv + 1) * chunk; + } else { + return ((cnt + chunk - 1) / chunk) * chunk; } - return cnt; } /** Check for the pointer alignment. From 21fc70c26fb8c14e531d8af1194e84309c6a72c6 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 5 Apr 2024 09:57:10 +0200 Subject: [PATCH 18/62] Cosmetic changes and minor code simplifications (#2806) --- src/coreneuron/io/mem_layout_util.cpp | 7 +++---- src/coreneuron/io/nrn_setup.cpp | 4 ++-- src/coreneuron/io/phase2.cpp | 12 +++++------- src/coreneuron/mechanism/mechanism.hpp | 6 +++--- src/nrncvode/netcvode.cpp | 2 +- .../callbacks/nrncore_callbacks.cpp | 16 +++++++++------- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/coreneuron/io/mem_layout_util.cpp b/src/coreneuron/io/mem_layout_util.cpp index 93d5d26f08..3845303425 100644 --- a/src/coreneuron/io/mem_layout_util.cpp +++ b/src/coreneuron/io/mem_layout_util.cpp @@ -20,8 +20,8 @@ int nrn_soa_padded_size(int cnt, int layout) { size_t nrn_soa_byte_align(size_t size) { static_assert(NRN_SOA_BYTE_ALIGN % sizeof(double) == 0, "NRN_SOA_BYTE_ALIGN should be a multiple of sizeof(double)"); - constexpr size_t dbl_align{NRN_SOA_BYTE_ALIGN / sizeof(double)}; - size_t remainder{size % dbl_align}; + constexpr size_t dbl_align = NRN_SOA_BYTE_ALIGN / sizeof(double); + size_t remainder = size % dbl_align; if (remainder) { size += dbl_align - remainder; } @@ -34,8 +34,7 @@ int nrn_i_layout(int icnt, int cnt, int isz, int sz, int layout) { case Layout::AoS: return icnt * sz + isz; case Layout::SoA: - int padded_cnt = nrn_soa_padded_size(cnt, - layout); // may want to factor out to save time + int padded_cnt = nrn_soa_padded_size(cnt, layout); return icnt + isz * padded_cnt; } diff --git a/src/coreneuron/io/nrn_setup.cpp b/src/coreneuron/io/nrn_setup.cpp index 888f07949a..e2752454e7 100644 --- a/src/coreneuron/io/nrn_setup.cpp +++ b/src/coreneuron/io/nrn_setup.cpp @@ -636,14 +636,14 @@ void read_phasegap(NrnThread& nt, UserParams& userParams) { // only voltage, i_membrane_ or mechanism data index allowed. (mtype 0 means time) double* stdindex2ptr(int mtype, int index, NrnThread& nt) { if (mtype == voltage) { // voltage - int ix{index}; // relative to _actual_v + int ix = index; // relative to _actual_v nrn_assert((ix >= 0) && (ix < nt.end)); if (nt._permute) { node_permute(&ix, 1, nt._permute); } return nt._actual_v + ix; } else if (mtype == i_membrane_) { // membrane current from fast_imem calculation - int ix{index}; // relative to nrn_fast_imem->nrn_sav_rhs + int ix = index; // relative to nrn_fast_imem->nrn_sav_rhs nrn_assert((ix >= 0) && (ix < nt.end)); if (nt._permute) { node_permute(&ix, 1, nt._permute); diff --git a/src/coreneuron/io/phase2.cpp b/src/coreneuron/io/phase2.cpp index 0502129068..0a62c2366c 100644 --- a/src/coreneuron/io/phase2.cpp +++ b/src/coreneuron/io/phase2.cpp @@ -315,8 +315,9 @@ void Phase2::read_direct(int thread_id, const NrnThread& nt) { auto& dparam_sizes = corenrn.get_prop_dparam_size(); int dsz_inst = 0; size_t offset = 6 * n_data_padded; - if (n_diam > 0) + if (n_diam > 0) { offset += n_data_padded; + } for (int i = 0; i < n_mech; ++i) { auto& tml = tmls[i]; int type = mech_types[i]; @@ -351,8 +352,9 @@ void Phase2::read_direct(int thread_id, const NrnThread& nt) { nmodlrandom, tml.pointer2type); - if (dparam_sizes[type] > 0) + if (dparam_sizes[type] > 0) { dsz_inst++; + } offset += nrn_soa_padded_size(nodecounts[i], layout) * param_sizes[type]; if (nodeindices_) { std::copy(nodeindices_, nodeindices_ + nodecounts[i], tml.nodeindices.data()); @@ -913,14 +915,10 @@ void Phase2::set_vec_play(NrnThread& nt, NrnThreadChkpnt& ntc) { nrn_assert(vecPlay.vtype == VecPlayContinuousType); #if CHKPNTDEBUG ntc.vtype[i] = vecPlay.vtype; -#endif -#if CHKPNTDEBUG ntc.mtype[i] = vecPlay.mtype; -#endif - Memb_list* ml = nt._ml_list[vecPlay.mtype]; -#if CHKPNTDEBUG ntc.vecplay_ix[i] = vecPlay.ix; #endif + Memb_list* ml = nt._ml_list[vecPlay.mtype]; vecPlay.ix = nrn_param_layout(vecPlay.ix, vecPlay.mtype, ml); if (ml->_permute) { diff --git a/src/coreneuron/mechanism/mechanism.hpp b/src/coreneuron/mechanism/mechanism.hpp index 9427423df7..45861fb410 100644 --- a/src/coreneuron/mechanism/mechanism.hpp +++ b/src/coreneuron/mechanism/mechanism.hpp @@ -143,12 +143,12 @@ struct Memb_list { NetSendBuffer_t* _net_send_buffer = nullptr; int nodecount; /* actual node count */ int _nodecount_padded; - void* instance{nullptr}; /* mechanism instance struct */ + void* instance = nullptr; /* mechanism instance struct */ // nrn_acc_manager.cpp handles data movement to/from the accelerator as the // "private constructor" in the translated MOD file code is called before // the main nrn_acc_manager methods that copy thread/mechanism data to the // device - void* global_variables{nullptr}; - std::size_t global_variables_size{}; + void* global_variables = nullptr; + std::size_t global_variables_size = 0; }; } // namespace coreneuron diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index 1573d190e4..f0421a92da 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -5567,7 +5567,7 @@ static int trajec_buffered(NrnThread& nt, // beyond their current size and CoreNEURON will start filling from the // current fill time, h.t, location of the arrays. I.e. starting at CoreNEURON's // start time. (Multiple calls to psolve append to these arrays.) -// n_pr refers the the number of PlayRecord instances in the vpr array. +// n_pr refers to the number of PlayRecord instances in the vpr array. // n_trajec refers to the number of trajectories to be recorded on the // CoreNEURON side and is the size of the types, indices, and varrays. // n_pr is different from n_trajec when one of the GLineRecord instances has diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 1c2e7bcfa1..381f21f812 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -168,16 +168,19 @@ size_t nrnthreads_type_return(int type, int tid, double*& data, std::vector 0 && type < n_memb_func) { + auto set_mdata = [type, tid, &mdata](Memb_list* ml) -> size_t { + mdata = ml->data(); + return ml->nodecount; + }; + Memb_list* ml = nt._ml_list[type]; if (ml) { - mdata = ml->data(); - n = ml->nodecount; + n = set_mdata(ml); } else { // The single thread case is easy if (nrn_nthread == 1) { ml = &memb_list[type]; - mdata = ml->data(); - n = ml->nodecount; + n = set_mdata(ml); } else { // mk_tml_with_art() created a cgs[id].mlwithart which appended // artificial cells to the end. Turns out that @@ -185,9 +188,8 @@ size_t nrnthreads_type_return(int type, int tid, double*& data, std::vectornodecount); - mdata = ml->data(); + Memb_list* ml = CellGroup::deferred_type2artml_[tid][type]; + n = set_mdata(ml); } } } From 3a3e8a681e6a888bb82813bf0135499cd547a3b4 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 5 Apr 2024 09:58:24 +0200 Subject: [PATCH 19/62] CMake: Globbing requires CONFIGURE_DEPENDS (#2808) --- cmake/NeuronTestHelper.cmake | 2 +- src/coreneuron/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/NeuronTestHelper.cmake b/cmake/NeuronTestHelper.cmake index 35a8ec5e6c..f377bcdddc 100644 --- a/cmake/NeuronTestHelper.cmake +++ b/cmake/NeuronTestHelper.cmake @@ -354,7 +354,7 @@ function(nrn_add_test) # We want to preserve directory structures, so if you pass SCRIPT_PATTERNS path/to/*.py then you # end up with {build_directory}/path/to/test_working_directory/path/to/script.py file( - GLOB script_files + GLOB script_files CONFIGURE_DEPENDS RELATIVE "${test_source_directory}/${sim_directory}" "${test_source_directory}/${sim_directory}/${script_pattern}") foreach(script_file ${script_files}) diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index 561b9896e3..28b8711f39 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -334,6 +334,7 @@ add_link_options(${CORENRN_EXTRA_LINK_FLAGS}) file( GLOB CORENEURON_CODE_FILES + CONFIGURE_DEPENDS "apps/main1.cpp" "apps/corenrn_parameters.cpp" "gpu/nrn_acc_manager.cpp" From 4eed6286f0116c5877607d29e2b480c541ffe747 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 5 Apr 2024 15:44:31 +0200 Subject: [PATCH 20/62] ltint is the default operator (#2816) --- src/parallel/bbsclimpi.cpp | 8 +------- src/parallel/bbsdirectmpi.cpp | 8 +------- src/parallel/bbslocal.cpp | 8 +------- src/parallel/bbslsrv.cpp | 10 ++-------- src/parallel/bbssrv2mpi.cpp | 12 +++--------- 5 files changed, 8 insertions(+), 38 deletions(-) diff --git a/src/parallel/bbsclimpi.cpp b/src/parallel/bbsclimpi.cpp index 4e95b5b336..5719006960 100644 --- a/src/parallel/bbsclimpi.cpp +++ b/src/parallel/bbsclimpi.cpp @@ -20,13 +20,7 @@ extern void nrnmpi_int_broadcast(int*, int, int); #include -struct ltint { - bool operator()(int i, int j) const { - return i < j; - } -}; - -class KeepArgs: public std::map {}; +class KeepArgs: public std::map {}; int BBSClient::sid_; diff --git a/src/parallel/bbsdirectmpi.cpp b/src/parallel/bbsdirectmpi.cpp index 4e62dbe0bf..711f98ade1 100644 --- a/src/parallel/bbsdirectmpi.cpp +++ b/src/parallel/bbsdirectmpi.cpp @@ -19,13 +19,7 @@ extern void nrnmpi_int_broadcast(int*, int, int); #define debug 0 -struct ltint { - bool operator()(int i, int j) const { - return i < j; - } -}; - -class KeepArgs: public std::map {}; +class KeepArgs: public std::map {}; BBSDirect::BBSDirect() { if (!BBSDirectServer::server_) { diff --git a/src/parallel/bbslocal.cpp b/src/parallel/bbslocal.cpp index 15ae4b8ee1..acfd8470ea 100644 --- a/src/parallel/bbslocal.cpp +++ b/src/parallel/bbslocal.cpp @@ -9,13 +9,7 @@ #include #include -struct ltint { - bool operator()(int i, int j) const { - return i < j; - } -}; - -class KeepArgs: public std::map {}; +class KeepArgs: public std::map {}; static MessageValue* posting_; static MessageValue* taking_; diff --git a/src/parallel/bbslsrv.cpp b/src/parallel/bbslsrv.cpp index b98dd212d1..d599f8ee23 100644 --- a/src/parallel/bbslsrv.cpp +++ b/src/parallel/bbslsrv.cpp @@ -33,12 +33,6 @@ struct ltstr { } }; -struct ltint { - bool operator()(int i, int j) const { - return i < j; - } -}; - struct ltWorkItem { bool operator()(const WorkItem* w1, const WorkItem* w2) const { return w1->todo_less_than(w2); @@ -86,9 +80,9 @@ bool WorkItem::todo_less_than(const WorkItem* w) const { } class MessageList: public std::multimap {}; -class WorkList: public std::map {}; +class WorkList: public std::map {}; class ReadyList: public std::set {}; -class ResultList: public std::multimap {}; +class ResultList: public std::multimap {}; MessageItem::MessageItem() { next_ = nullptr; diff --git a/src/parallel/bbssrv2mpi.cpp b/src/parallel/bbssrv2mpi.cpp index 0a2776445e..cb5c159a13 100644 --- a/src/parallel/bbssrv2mpi.cpp +++ b/src/parallel/bbssrv2mpi.cpp @@ -43,12 +43,6 @@ struct ltstr { } }; -struct ltint { - bool operator()(int i, int j) const { - return i < j; - } -}; - struct ltWorkItem { bool operator()(const WorkItem* w1, const WorkItem* w2) const { return w1->todo_less_than(w2); @@ -95,10 +89,10 @@ bool WorkItem::todo_less_than(const WorkItem* w) const { class MessageList: public std::multimap {}; class PendingList: public std::multimap {}; -class WorkList: public std::map {}; -class LookingToDoList: public std::set {}; +class WorkList: public std::map {}; +class LookingToDoList: public std::set {}; class ReadyList: public std::set {}; -class ResultList: public std::multimap {}; +class ResultList: public std::multimap {}; BBSDirectServer::BBSDirectServer() { messages_ = new MessageList(); From 6eca3127b748647c21b56cf106f5c6d551bb05e3 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 5 Apr 2024 16:54:26 +0200 Subject: [PATCH 21/62] Use override instead of virtual (#2817) --- src/parallel/bbsdirect.h | 64 ++++++++++++++++++++-------------------- src/parallel/bbslocal.h | 62 +++++++++++++++++++------------------- src/parallel/bbsrcli.h | 58 ++++++++++++++++++------------------ 3 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/parallel/bbsdirect.h b/src/parallel/bbsdirect.h index b5679dbceb..9c595b710d 100644 --- a/src/parallel/bbsdirect.h +++ b/src/parallel/bbsdirect.h @@ -15,43 +15,43 @@ struct bbsmpibuf; class BBSDirect: public BBSImpl { public: BBSDirect(); - virtual ~BBSDirect(); + ~BBSDirect() override; - virtual bool look(const char*); + bool look(const char*) override; - virtual void take(const char*); /* blocks til something to take */ - virtual bool look_take(const char*); /* returns false if nothing to take */ + void take(const char*) override; /* blocks til something to take */ + bool look_take(const char*) override; /* returns false if nothing to take */ // after taking use these - virtual int upkint(); - virtual double upkdouble(); - virtual void upkvec(int, double*); - virtual char* upkstr(); // delete [] char* when finished - virtual char* upkpickle(size_t*); // delete [] char* when finished + int upkint() override; + double upkdouble() override; + void upkvec(int, double*) override; + char* upkstr() override; // delete [] char* when finished + char* upkpickle(size_t*) override; // delete [] char* when finished // before posting use these - virtual void pkbegin(); - virtual void pkint(int); - virtual void pkdouble(double); - virtual void pkvec(int, double*); - virtual void pkstr(const char*); - virtual void pkpickle(const char*, size_t); - virtual void post(const char*); - - virtual void post_todo(int parentid); - virtual void post_result(int id); - virtual int look_take_result(int pid); // returns id, or 0 if nothing - virtual int master_take_result(int pid); // returns id - virtual int look_take_todo(); // returns id, or 0 if nothing - virtual int take_todo(); // returns id - virtual void save_args(int); - virtual void return_args(int); - - virtual void context(); - - virtual void start(); - virtual void done(); - - virtual void perror(const char*); + void pkbegin() override; + void pkint(int) override; + void pkdouble(double) override; + void pkvec(int, double*) override; + void pkstr(const char*) override; + void pkpickle(const char*, size_t) override; + void post(const char*) override; + + void post_todo(int parentid) override; + void post_result(int id) override; + int look_take_result(int pid) override; // returns id, or 0 if nothing + int master_take_result(int pid) override; // returns id + int look_take_todo() override; // returns id, or 0 if nothing + int take_todo() override; // returns id + void save_args(int) override; + void return_args(int) override; + + void context() override; + + void start() override; + void done() override; + + void perror(const char*) override; private: KeepArgs* keepargs_; diff --git a/src/parallel/bbslocal.h b/src/parallel/bbslocal.h index 920ea557f3..dba6051a23 100644 --- a/src/parallel/bbslocal.h +++ b/src/parallel/bbslocal.h @@ -7,42 +7,42 @@ class KeepArgs; class BBSLocal: public BBSImpl { public: BBSLocal(); - virtual ~BBSLocal(); + ~BBSLocal() override; - virtual bool look(const char*); + bool look(const char*) override; - virtual void take(const char*); /* blocks til something to take */ - virtual bool look_take(const char*); /* returns false if nothing to take */ + void take(const char*) override; /* blocks til something to take */ + bool look_take(const char*) override; /* returns false if nothing to take */ // after taking use these - virtual int upkint(); - virtual double upkdouble(); - virtual void upkvec(int, double*); - virtual char* upkstr(); // delete [] char* when finished - virtual char* upkpickle(size_t* size); // delete [] char* when finished + int upkint() override; + double upkdouble() override; + void upkvec(int, double*) override; + char* upkstr() override; // delete [] char* when finished + char* upkpickle(size_t* size) override; // delete [] char* when finished // before posting use these - virtual void pkbegin(); - virtual void pkint(int); - virtual void pkdouble(double); - virtual void pkvec(int, double*); - virtual void pkstr(const char*); - virtual void pkpickle(const char*, size_t); - virtual void post(const char*); - - virtual void post_todo(int parentid); - virtual void post_result(int id); - virtual int look_take_result(int pid); // returns id, or 0 if nothing - virtual int look_take_todo(); // returns id, or 0 if nothing - virtual int take_todo(); // returns id - virtual void save_args(int); - virtual void return_args(int); - - virtual void context(); - - virtual void start(); - virtual void done(); - - virtual void perror(const char*); + void pkbegin() override; + void pkint(int) override; + void pkdouble(double) override; + void pkvec(int, double*) override; + void pkstr(const char*) override; + void pkpickle(const char*, size_t) override; + void post(const char*) override; + + void post_todo(int parentid) override; + void post_result(int id) override; + int look_take_result(int pid) override; // returns id, or 0 if nothing + int look_take_todo() override; // returns id, or 0 if nothing + int take_todo() override; // returns id + void save_args(int) override; + void return_args(int) override; + + void context() override; + + void start() override; + void done() override; + + void perror(const char*) override; private: KeepArgs* keepargs_; diff --git a/src/parallel/bbsrcli.h b/src/parallel/bbsrcli.h index 70bcfa3790..72ef12a9ab 100644 --- a/src/parallel/bbsrcli.h +++ b/src/parallel/bbsrcli.h @@ -8,40 +8,40 @@ struct bbsmpibuf; class BBSClient: public BBSImpl { // implemented as PVM Client public: BBSClient(); - virtual ~BBSClient(); + ~BBSClient() override; - virtual bool look(const char*); + bool look(const char*) override; - virtual void take(const char*); /* blocks til something to take */ - virtual bool look_take(const char*); /* returns false if nothing to take */ + void take(const char*) override; /* blocks til something to take */ + bool look_take(const char*) override; /* returns false if nothing to take */ // after taking use these - virtual int upkint(); - virtual double upkdouble(); - virtual void upkvec(int, double*); - virtual char* upkstr(); // delete [] char* when finished - virtual char* upkpickle(size_t*); // delete [] char* when finished + int upkint() override; + double upkdouble() override; + void upkvec(int, double*) override; + char* upkstr() override; // delete [] char* when finished + char* upkpickle(size_t*) override; // delete [] char* when finished // before posting use these - virtual void pkbegin(); - virtual void pkint(int); - virtual void pkdouble(double); - virtual void pkvec(int, double*); - virtual void pkstr(const char*); - virtual void pkpickle(const char*, size_t); - virtual void post(const char*); - - virtual void post_todo(int parentid); - virtual void post_result(int id); - virtual int look_take_result(int pid); // returns id, or 0 if nothing - virtual int look_take_todo(); // returns id, or 0 if nothing - virtual int take_todo(); // returns id - virtual void save_args(int); - virtual void return_args(int); - - virtual void start(); - virtual void done(); - - virtual void perror(const char*); + void pkbegin() override; + void pkint(int) override; + void pkdouble(double) override; + void pkvec(int, double*) override; + void pkstr(const char*) override; + void pkpickle(const char*, size_t) override; + void post(const char*) override; + + void post_todo(int parentid) override; + void post_result(int id) override; + int look_take_result(int pid) override; // returns id, or 0 if nothing + int look_take_todo() override; // returns id, or 0 if nothing + int take_todo() override; // returns id + void save_args(int) override; + void return_args(int) override; + + void start() override; + void done() override; + + void perror(const char*) override; private: int get(const char* key, int type); // return type From 13b5dc0fef78f3a01d0c3972f3c2ebc4865280b8 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 5 Apr 2024 17:47:35 +0200 Subject: [PATCH 22/62] Fix build-time dependency bug. (#2814) * Fix build-time dependency bug. To manifest this bug one must: 1. Configure and build the project with CoreNEURON. 2. Edit a file that's added to `coreneuron-core`, e.g. `coreneuron/io/mem_layout_util.cpp`, e.g. in by breaking `nrn_param_layout`. 3. Recompile and run the tests, e.g. `-R coreneuron_modtests`. These test should now fail because a bug has been introduced. However, due to broken dependency chain `nrnivmodl` will not be run. Hence, test/nrnivmodl/${sha}/x86_64/libcorenrnmech.so and `special` will not be updated and continue to use the old code. * Idea 1: Avoid `coreneuron-for-tests`. This leads to a broken dependency on `nmodl`. Meaning `nrnivmodl` can error out claiming `bin/nmodl` doesn't exist. * Idea 2: Retain the custom target. Seems to have no affect at all. * Revert Idea 1 & 2. * Idea 3: add `coreneuron-core` directly. --- cmake/NeuronTestHelper.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/NeuronTestHelper.cmake b/cmake/NeuronTestHelper.cmake index f377bcdddc..405a5d7736 100644 --- a/cmake/NeuronTestHelper.cmake +++ b/cmake/NeuronTestHelper.cmake @@ -163,6 +163,7 @@ function(nrn_add_test_group) if(NRN_ADD_TEST_GROUP_CORENEURON AND NRN_ENABLE_CORENEURON) list(APPEND hash_components -coreneuron) list(APPEND nrnivmodl_dependencies ${CORENEURON_TARGET_TO_DEPEND}) + list(APPEND nrnivmodl_dependencies coreneuron-core) list(APPEND nrnivmodl_command -coreneuron) endif() list(APPEND nrnivmodl_command .) From cc05aed8b089212874b49aacdff2d2670cb2bf99 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Fri, 5 Apr 2024 18:09:38 +0200 Subject: [PATCH 23/62] Remove `strings.h` header (#2812) Remove all references to `STDC_HEADERS` They are defined by the standard, and any compiler worth anything should implement these, so we should not need them anymore --- cmake/ConfigFileSetting.cmake | 10 ---------- cmake_nrnconf.h.in | 7 ------- src/modlunit/declare.cpp | 11 ++--------- src/modlunit/io.cpp | 1 + src/modlunit/list.cpp | 1 + src/modlunit/model.cpp | 1 + src/modlunit/model.h | 7 ------- src/modlunit/nrnunit.cpp | 1 + src/modlunit/parse1.ypp | 1 + src/modlunit/symbol.cpp | 1 + src/sundials/sundials_config.h.in | 3 --- 11 files changed, 8 insertions(+), 36 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index a6bde94287..9a44ce8c94 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -120,24 +120,14 @@ set(SUNDIALS_USE_GENERIC_MATH 1) nrn_check_include_files(dlfcn.h HAVE_DLFCN_H) nrn_check_include_files(execinfo.h HAVE_EXECINFO_H) nrn_check_include_files(malloc.h HAVE_MALLOC_H) -nrn_check_include_files(strings.h HAVE_STRINGS_H) nrn_check_include_files(sys/types.h HAVE_SYS_TYPES_H) nrn_check_include_files(unistd.h HAVE_UNISTD_H) -# ============================================================================= -# Check for standard headers -# ============================================================================= -check_include_files("dlfcn.h;stdint.h;stddef.h;inttypes.h;stdlib.h;strings.h;string.h;float.h" - STDC_HEADERS) - # ============================================================================= # Check symbol using check_cxx_symbol_exists but use ${NRN_HEADERS_INCLUDE_LIST} # ============================================================================= # note that this must be called after all *check_include_files because we use # NRN_HEADERS_INCLUDE_LIST is second argument (headers) is empty. -nrn_check_symbol_exists("bcopy" "strings.h" HAVE_BCOPY) -nrn_check_symbol_exists("bzero" "strings.h" HAVE_BZERO) -nrn_check_symbol_exists("index" "strings.h" HAVE_INDEX) nrn_check_symbol_exists("isatty" "unistd.h" HAVE_ISATTY) nrn_check_symbol_exists("iv" "" HAVE_IV) nrn_check_symbol_exists("mallinfo" "malloc.h" HAVE_MALLINFO) diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 57436d1977..0ee0723bad 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -64,9 +64,6 @@ /* (Define if this signal exists) */ #undef HAVE_SIGBUS -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H @@ -132,9 +129,6 @@ STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - /* Define SUNDIALS data type 'realtype' as 'long double' */ #undef SUNDIALS_DOUBLE_PRECISION @@ -204,4 +198,3 @@ namespace neuron::config { #endif #endif /* H_nrnconf_included */ - diff --git a/src/modlunit/declare.cpp b/src/modlunit/declare.cpp index 148ba093a4..22a4b066f6 100644 --- a/src/modlunit/declare.cpp +++ b/src/modlunit/declare.cpp @@ -1,11 +1,9 @@ #include <../../nmodlconf.h> #include +#include #include "model.h" #include "parse1.hpp" #include "symbol.h" -#ifdef HAVE_STRINGS_H -#include -#endif Symbol* indepsym; /* mathematical independent variable */ Item** scop_indep; /* the scop swept information */ @@ -195,15 +193,10 @@ Symbol* basestate(Symbol* s) /* base state symbol for state''' or state0 */ return base; } -#if SYSV || !defined(HAVE_INDEX) || defined(HAVE_STRINGS_H) -#undef index -#define index strchr -#endif - static int nprime(char* s) { char* cp; - cp = index(s, '\''); + cp = strchr(s, '\''); return strlen(s) - (cp - s); } diff --git a/src/modlunit/io.cpp b/src/modlunit/io.cpp index 93b36a6557..05efb0c536 100644 --- a/src/modlunit/io.cpp +++ b/src/modlunit/io.cpp @@ -3,6 +3,7 @@ /* file.mod input routines */ #include +#include #include "model.h" #include #undef METHOD diff --git a/src/modlunit/list.cpp b/src/modlunit/list.cpp index 88bea2d255..25c69f1bfd 100644 --- a/src/modlunit/list.cpp +++ b/src/modlunit/list.cpp @@ -30,6 +30,7 @@ following function calls. */ #include +#include #include "model.h" #include "parse1.hpp" diff --git a/src/modlunit/model.cpp b/src/modlunit/model.cpp index 29005268fc..3ae156cce5 100644 --- a/src/modlunit/model.cpp +++ b/src/modlunit/model.cpp @@ -24,6 +24,7 @@ * still gives the prefix of the .c and .var files. */ +#include #include "model.h" #include "parse1.hpp" diff --git a/src/modlunit/model.h b/src/modlunit/model.h index 2433436c53..fcc644d6b0 100644 --- a/src/modlunit/model.h +++ b/src/modlunit/model.h @@ -1,13 +1,6 @@ /* /local/src/master/nrn/src/modlunit/model.h,v 1.2 1997/11/24 16:19:13 hines Exp */ #include "wrap_sprintf.h" #include -#if 1 -#if defined(STDC_HEADERS) || defined(SYSV) -#include -#else -#include -#endif -#endif #include #define NRN_BUFSIZE 8192 diff --git a/src/modlunit/nrnunit.cpp b/src/modlunit/nrnunit.cpp index fa71749b68..035beb2a94 100644 --- a/src/modlunit/nrnunit.cpp +++ b/src/modlunit/nrnunit.cpp @@ -1,4 +1,5 @@ #include <../../nmodlconf.h> +#include #include "model.h" #include "units.h" #include "parse1.hpp" diff --git a/src/modlunit/parse1.ypp b/src/modlunit/parse1.ypp index 6e0e4778b3..a10bf05f88 100755 --- a/src/modlunit/parse1.ypp +++ b/src/modlunit/parse1.ypp @@ -3,6 +3,7 @@ #include <../../nmodlconf.h> #include +#include #include "model.h" /* Constructs a parse tree. No translation is done, ie. on exit printing diff --git a/src/modlunit/symbol.cpp b/src/modlunit/symbol.cpp index 7af671c526..bc23e79ccc 100644 --- a/src/modlunit/symbol.cpp +++ b/src/modlunit/symbol.cpp @@ -1,5 +1,6 @@ #include <../../nmodlconf.h> /* /local/src/master/nrn/src/modlunit/symbol.c,v 1.1.1.1 1994/10/12 17:22:50 hines Exp */ +#include #include "model.h" #include "parse1.hpp" diff --git a/src/sundials/sundials_config.h.in b/src/sundials/sundials_config.h.in index 49977f3819..a043f1ed48 100755 --- a/src/sundials/sundials_config.h.in +++ b/src/sundials/sundials_config.h.in @@ -42,9 +42,6 @@ /* The size of a `long int', as computed by sizeof. */ #undef SIZEOF_LONG_INT -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - /* FCMIX: Make function names lowercase */ #undef SUNDIALS_CASE_LOWER From aba7266753edc86634cce54b506a0f033c20ca78 Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Fri, 5 Apr 2024 18:26:15 +0200 Subject: [PATCH 24/62] Part II: Increase memory available for Gitlab CI jobs on BB5 (#2794) See #2793 - which was made merged a bit too early. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d06798d067..dd586ea86b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -167,7 +167,7 @@ simulation_stack: variables: bb5_ntasks: 2 # so we block 16 cores bb5_cpus_per_task: 8 # ninja -j {this} - bb5_memory: 120G # ~1.5*16*384/80 (~1.5x more as we have seen OOMs) + bb5_memory: 160G # ~2*16*384/80 (~2x more as we have seen OOMs) .spack_intel: variables: @@ -192,7 +192,7 @@ simulation_stack: extends: [.ctest] variables: bb5_ntasks: 16 - bb5_memory: 120G # ~1.5*16*384/80 (~1.5x more as we have seen OOMs) + bb5_memory: 160G # ~2*16*384/80 (~2x more as we have seen OOMs) # Build NMODL once with GCC build:nmodl: From 2ec360bdb18a71c01428af25b04894e6fe027c32 Mon Sep 17 00:00:00 2001 From: Weina Ji Date: Sat, 6 Apr 2024 00:29:05 +0200 Subject: [PATCH 25/62] Fix setter decorators for some coreneuron attributes (#2770) * keep coreneuron init values for other tests --- share/lib/python/neuron/coreneuron.py | 14 +++++------ test/coreneuron/test_spikes.py | 2 +- .../test_coreneuron_configuration.py | 24 +++++++++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 test/pytest_coreneuron/test_coreneuron_configuration.py diff --git a/share/lib/python/neuron/coreneuron.py b/share/lib/python/neuron/coreneuron.py index b384614a23..d20c9cf033 100644 --- a/share/lib/python/neuron/coreneuron.py +++ b/share/lib/python/neuron/coreneuron.py @@ -235,27 +235,27 @@ def model_path(self): """Data path of the model.""" return self._model_path - @sim_config.setter + @model_path.setter def model_path(self, value): - self._model_path = str(value) + self._model_path = str(value) if value else value @property def save_path(self): """Data path for save.""" return self._save_path - @sim_config.setter + @save_path.setter def save_path(self, value): - self._save_path = str(value) + self._save_path = str(value) if value else value @property def restore_path(self): """Data path for restore.""" return self._restore_path - @sim_config.setter + @restore_path.setter def restore_path(self, value): - self._restore_path = str(value) + self._restore_path = str(value) if value else value @property def skip_write_model_to_disk(self): @@ -268,7 +268,7 @@ def skip_write_model_to_disk(self): """ return self._skip_write_model_to_disk - @sim_config.setter + @skip_write_model_to_disk.setter def skip_write_model_to_disk(self, value): self._skip_write_model_to_disk = value diff --git a/test/coreneuron/test_spikes.py b/test/coreneuron/test_spikes.py index 6522774648..cecb8a3d0e 100644 --- a/test/coreneuron/test_spikes.py +++ b/test/coreneuron/test_spikes.py @@ -127,7 +127,7 @@ def run(mode): coreneuron.model_path = "coreneuron_input" run(0) # revert setting for the following coreneuron runs - coreneuron._model_path = None + coreneuron.model_path = None return h diff --git a/test/pytest_coreneuron/test_coreneuron_configuration.py b/test/pytest_coreneuron/test_coreneuron_configuration.py new file mode 100644 index 0000000000..cd6f158d97 --- /dev/null +++ b/test/pytest_coreneuron/test_coreneuron_configuration.py @@ -0,0 +1,24 @@ +from neuron import coreneuron + + +def test_coreneuron_configuration(): + with coreneuron( + restore_path="restore", + save_path="save", + model_path="coredat", + skip_write_model_to_disk=True, + ): + assert coreneuron.restore_path == "restore" + assert coreneuron.save_path == "save" + assert coreneuron.model_path == "coredat" + assert coreneuron.skip_write_model_to_disk == True + + # back to the old values outside the "with" context + assert coreneuron.restore_path is None + assert coreneuron.save_path is None + assert coreneuron.model_path is None + assert coreneuron.skip_write_model_to_disk == False + + +if __name__ == "__main__": + test_coreneuron_configuration() From 4970d60f35243ecb496852c034fe5ce119bb378c Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Sat, 6 Apr 2024 11:21:32 +0200 Subject: [PATCH 26/62] Make SPTree a class (#2748) --- src/nrncvode/sptree.hpp | 702 ++++++++++++++++------------------------ src/nrncvode/tqueue.cpp | 45 ++- src/nrncvode/tqueue.hpp | 4 +- 3 files changed, 296 insertions(+), 455 deletions(-) diff --git a/src/nrncvode/sptree.hpp b/src/nrncvode/sptree.hpp index bc78cd3180..5ef997e38b 100644 --- a/src/nrncvode/sptree.hpp +++ b/src/nrncvode/sptree.hpp @@ -7,129 +7,141 @@ ** ** assumes that key will be provided by the application, comparable ** with the compare function applied to the addresses of two keys. +** +** Originaly written by Douglas W. Jones in Fortran helped by Srinivas R. Sataluri. +** Translated by David Brower to C circa 1988. +** Some fixes by Mark Moraes . +** +** For some litterature about this Splay tree: https://en.wikipedia.org/wiki/Splay_tree +** The original implementation is based on: +** Self Adjusting Binary Trees +** by D. D. Sleator and R. E. Tarjan, +** Proc. ACM SIGACT Symposium on Theory +** of Computing (Boston, Apr 1983) 235-245. +** +** For more insights, `enqueue` is doing the splay top-down. +** `splay` itself is doing it bottom-up. */ #pragma once -#define STRCMP(a, b) (a - b) - -template -struct SPTREE { - SPBLK* root; /* root node */ - - int enqcmps; /* compares in spenq */ +#include + +template +class SPTree { + public: + SPTree() = default; + + // Is this SPTree empty? + bool empty() const; + + // Return the value of enqcmps. + int get_enqcmps() const; + + // Insert item in the tree. + // + // Put `n` after all other nodes with the same key; when this is + // done, `n` will be the root of the splay tree, all nodes + // with keys less than or equal to that of `n` will be in the + // left subtree, all with greater keys will be in the right subtree; + // the tree is split into these subtrees from the top down, with rotations + // performed along the way to shorten the left branch of the right subtree + // and the right branch of the left subtree + void enqueue(T* n); + + // Return and remove the first node. + // + // Remove and return the first node; this deletes + // (and returns) the leftmost node, replacing it with its right + // subtree (if there is one); on the way to the leftmost node, rotations + // are performed to shorten the left branch of the tree. + T* dequeue(); + + // Return the element in the tree with the lowest key. + // + // Returns a pointer to the item with the lowest key. + // The left branch will be shortened as if the tree had been splayed around the first item. + // This is done by dequeue and enqueuing the first item. + T* first(); + + // Remove node `n` from the tree. + // + // `n` is removed; the resulting splay tree has been splayed + // around its new root, which is the successor of n + void remove(T* n); + + // Find a node with the given key. + // + // Splays the found node to the root. + T* find(double key); + + // Apply the function `f` to each node in ascending order. + // + // `f` is the function that will be applied to nodes. The first argument will be + // a pointer to the current node, the integer value is unused and will always be `0`. + // If n is given, start at that node, otherwise start from the head. + void apply_all(void (*f)(const T*, int), T* n) const; + + private: + // Dequeue the first node in the subtree np + T* dequeue(T** np); + + // Reorganize the tree. + // + // The tree is reorganized so that `n` is the root of the + // splay tree; operation is undefined if `n` is not + // in the tree; the tree is split from `n` up to the old root, with all + // nodes to the left of `n` ending up in the left subtree, and all nodes + // to the right of n ending up in the right subtree; the left branch of + // the right subtree and the right branch of the left subtree are + // shortened in the process + // + // This code assumes that `n` is not `nullptr` and is in the tree; it can sometimes + // detect that `n` is not in the tree and throw an exception. + void splay(T* n); + + // Return the first element in the tree witout splaying. + // + // Returns a reference to the head event. + // Avoids splaying but just searches for and returns a pointer to + // the bottom of the left branch. + T* fast_first() const; + + // Fast return next higher item in the tree, or nullptr + // + // Return the successor of `n`, represented as a splay tree. + // This is a fast (on average) version that does not splay. + T* fast_next(T* n) const; + + // The node at the top of the tree + T* root{}; + + // Number of comparison in enqueue + int enqcmps{}; }; -#define spinit sptq_spinit -#define spempty sptq_spempty -#define spenq sptq_spenq -#define spdeq sptq_spdeq -#define splay sptq_splay -#define sphead sptq_sphead -#define spdelete sptq_spdelete -#define splookup sptq_splookup -#define spscan sptq_spscan -#define spfhead sptq_spfhead -#define spfnext sptq_spfnext - -/* Original file: sptree.cpp - * - * sptree.cpp: The following code implements the basic operations on - * an event-set or priority-queue implemented using splay trees: - * -Hines changed to void spinit(SPTREE**) for use with TQueue. - * SPTREE *spinit( compare ) Make a new tree - * int spempty(); Is tree empty? - * SPBLK *spenq( n, q ) Insert n in q after all equal keys. - * SPBLK *spdeq( np ) Return first key under *np, removing it. - * void splay( n, q ) n (already in q) becomes the root. - * - * In the above, n points to an SPBLK type, while q points to an - * SPTREE. - * - * The implementation used here is based on the implementation - * which was used in the tests of splay trees reported in: - * - * An Empirical Comparison of Priority-Queue and Event-Set Implementations, - * by Douglas W. Jones, Comm. ACM 29, 4 (Apr. 1986) 300-311. - * - * The changes made include the addition of the enqprior - * operation and the addition of up-links to allow for the splay - * operation. The basic splay tree algorithms were originally - * presented in: - * - * Self Adjusting Binary Trees, - * by D. D. Sleator and R. E. Tarjan, - * Proc. ACM SIGACT Symposium on Theory - * of Computing (Boston, Apr 1983) 235-245. - * - * The enq and enqprior routines use variations on the - * top-down splay operation, while the splay routine is bottom-up. - * All are coded for speed. - * - * Written by: - * Douglas W. Jones - * - * Translated to C by: - * David Brower, daveb@rtech.uucp - * - * Thu Oct 6 12:11:33 PDT 1988 (daveb) Fixed spdeq, which was broken - * handling one-node trees. I botched the pascal translation of - * a VAR parameter. - */ - - -/* USER SUPPLIED! */ - -/*extern char *emalloc();*/ - - -/*---------------- - * - * spinit() -- initialize an empty splay tree - * - */ -template -void spinit(SPTREE* q) { - q->enqcmps = 0; - q->root = nullptr; +template +bool SPTree::empty() const { + return root == nullptr; } -/*---------------- - * - * spempty() -- is an event-set represented as a splay tree empty? - */ -template -bool spempty(SPTREE* q) { - return (q == nullptr || q->root == nullptr); +template +int SPTree::get_enqcmps() const { + return enqcmps; } - -/*---------------- - * - * spenq() -- insert item in a tree. - * - * put n in q after all other nodes with the same key; when this is - * done, n will be the root of the splay tree representing q, all nodes - * in q with keys less than or equal to that of n will be in the - * left subtree, all with greater keys will be in the right subtree; - * the tree is split into these subtrees from the top down, with rotations - * performed along the way to shorten the left branch of the right subtree - * and the right branch of the left subtree - */ -template -SPBLK* spenq(SPBLK* n, SPTREE* q) { - SPBLK* left; /* the rightmost node in the left tree */ - SPBLK* right; /* the leftmost node in the right tree */ - SPBLK* next; /* the root of the unsplit part */ - SPBLK* temp; +template +void SPTree::enqueue(T* n) { + T* left; /* the rightmost node in the left tree */ + T* right; /* the leftmost node in the right tree */ + T* next; /* the root of the unsplit part */ + T* temp; double key; - int Sct; /* Strcmp value */ n->uplink = nullptr; - next = q->root; - q->root = n; + next = root; + root = n; if (next == nullptr) /* trivial enq */ { n->leftlink = nullptr; @@ -144,12 +156,12 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { splayed trees resulting from splitting on n->key; note that the children will be reversed! */ - q->enqcmps++; - if (STRCMP(next->key, key) > 0) + enqcmps++; + if (next->key - key > 0) { goto two; + } - one: /* assert next->key <= key */ - + one: /* assert next->key <= key */ do /* walk to the right in the left tree */ { temp = next->rightlink; @@ -160,8 +172,8 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { goto done; /* job done, entire tree split */ } - q->enqcmps++; - if (STRCMP(temp->key, key) > 0) { + enqcmps++; + if (temp->key - key > 0) { left->rightlink = next; next->uplink = left; left = next; @@ -170,8 +182,9 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { } next->rightlink = temp->leftlink; - if (temp->leftlink != nullptr) + if (temp->leftlink != nullptr) { temp->leftlink->uplink = next; + } left->rightlink = temp; temp->uplink = left; temp->leftlink = next; @@ -183,12 +196,11 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { goto done; /* job done, entire tree split */ } - q->enqcmps++; - - } while (STRCMP(next->key, key) <= 0); /* change sides */ + enqcmps++; - two: /* assert next->key > key */ + } while (next->key - key <= 0); /* change sides */ + two: /* assert next->key > key */ do /* walk to the left in the right tree */ { temp = next->leftlink; @@ -199,8 +211,8 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { goto done; /* job done, entire tree split */ } - q->enqcmps++; - if (STRCMP(temp->key, key) <= 0) { + enqcmps++; + if (temp->key - key <= 0) { right->leftlink = next; next->uplink = right; right = next; @@ -208,8 +220,9 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { goto one; /* change sides */ } next->leftlink = temp->rightlink; - if (temp->rightlink != nullptr) + if (temp->rightlink != nullptr) { temp->rightlink->uplink = next; + } right->leftlink = temp; temp->uplink = right; temp->rightlink = next; @@ -221,42 +234,32 @@ SPBLK* spenq(SPBLK* n, SPTREE* q) { goto done; /* job done, entire tree split */ } - q->enqcmps++; + enqcmps++; - } while (STRCMP(next->key, key) > 0); /* change sides */ + } while (next->key - key > 0); /* change sides */ goto one; - done: /* split is done, branches of n need reversal */ - + done: /* split is done, branches of `n` need reversal */ temp = n->leftlink; n->leftlink = n->rightlink; n->rightlink = temp; } +} - return (n); - -} /* spenq */ - - -/*---------------- - * - * spdeq() -- return and remove head node from a subtree. - * - * remove and return the head node from the node set; this deletes - * (and returns) the leftmost node from q, replacing it with its right - * subtree (if there is one); on the way to the leftmost node, rotations - * are performed to shorten the left branch of the tree - */ -template -SPBLK* spdeq(SPBLK** np) /* pointer to a node pointer */ +template +T* SPTree::dequeue() { + return dequeue(&root); +} +template +T* SPTree::dequeue(T** np) /* pointer to a node pointer */ { - SPBLK* deq; /* one to return */ - SPBLK* next; /* the next thing to deal with */ - SPBLK* left; /* the left child of next */ - SPBLK* farleft; /* the left child of left */ - SPBLK* farfarleft; /* the left child of farleft */ + T* deq; /* one to return */ + T* next; /* the next thing to deal with */ + T* left; /* the left child of next */ + T* farleft; /* the left child of left */ + T* farfarleft; /* the left child of farleft */ if (np == nullptr || *np == nullptr) { deq = nullptr; @@ -267,10 +270,10 @@ SPBLK* spdeq(SPBLK** np) /* pointer to a node pointer */ deq = next; *np = next->rightlink; - if (*np != nullptr) + if (*np != nullptr) { (*np)->uplink = nullptr; - - } else + } + } else { for (;;) /* left is not null */ { /* next is not it, left is not nullptr, might be it */ @@ -304,37 +307,20 @@ SPBLK* spdeq(SPBLK** np) /* pointer to a node pointer */ next = farleft; left = farfarleft; } + } } - return (deq); - -} /* spdeq */ - - -/*---------------- - * - * splay() -- reorganize the tree. - * - * the tree is reorganized so that n is the root of the - * splay tree representing q; results are unpredictable if n is not - * in q to start with; q is split from n up to the old root, with all - * nodes to the left of n ending up in the left subtree, and all nodes - * to the right of n ending up in the right subtree; the left branch of - * the right subtree and the right branch of the left subtree are - * shortened in the process - * - * this code assumes that n is not nullptr and is in q; it can sometimes - * detect n not in q and complain - */ - -template -void splay(SPBLK* n, SPTREE* q) { - SPBLK* up; /* points to the node being dealt with */ - SPBLK* prev; /* a descendent of up, already dealt with */ - SPBLK* upup; /* the parent of up */ - SPBLK* upupup; /* the grandparent of up */ - SPBLK* left; /* the top of left subtree being built */ - SPBLK* right; /* the top of right subtree being built */ + return deq; +} + +template +void SPTree::splay(T* n) { + T* up; /* points to the node being dealt with */ + T* prev; /* a descendent of up, already dealt with */ + T* upup; /* the parent of up */ + T* upupup; /* the grandparent of up */ + T* left; /* the top of left subtree being built */ + T* right; /* the top of right subtree being built */ left = n->leftlink; @@ -344,8 +330,7 @@ void splay(SPBLK* n, SPTREE* q) { while (up != nullptr) { /* walk up the tree towards the root, splaying all to the left of - n into the left subtree, all to right into the right subtree */ - + `n` into the left subtree, all to right into the right subtree */ upup = up->uplink; if (up->leftlink == prev) /* up is to the right of n */ { @@ -353,46 +338,52 @@ void splay(SPBLK* n, SPTREE* q) { { upupup = upup->uplink; upup->leftlink = up->rightlink; - if (upup->leftlink != nullptr) + if (upup->leftlink != nullptr) { upup->leftlink->uplink = upup; + } up->rightlink = upup; upup->uplink = up; - if (upupup == nullptr) - q->root = up; - else if (upupup->leftlink == upup) + if (upupup == nullptr) { + root = up; + } else if (upupup->leftlink == upup) { upupup->leftlink = up; - else + } else { upupup->rightlink = up; + } up->uplink = upupup; upup = upupup; } up->leftlink = right; - if (right != nullptr) + if (right != nullptr) { right->uplink = up; + } right = up; - } else /* up is to the left of n */ + } else /* up is to the left of `n` */ { if (upup != nullptr && upup->rightlink == up) /* rotate */ { upupup = upup->uplink; upup->rightlink = up->leftlink; - if (upup->rightlink != nullptr) + if (upup->rightlink != nullptr) { upup->rightlink->uplink = upup; + } up->leftlink = upup; upup->uplink = up; - if (upupup == nullptr) - q->root = up; - else if (upupup->rightlink == upup) + if (upupup == nullptr) { + root = up; + } else if (upupup->rightlink == upup) { upupup->rightlink = up; - else + } else { upupup->leftlink = up; + } up->uplink = upupup; upup = upupup; } up->rightlink = left; - if (left != nullptr) + if (left != nullptr) { left->uplink = up; + } left = up; } prev = up; @@ -400,278 +391,129 @@ void splay(SPBLK* n, SPTREE* q) { } #ifdef DEBUG - if (q->root != prev) { - /* fprintf(stderr, " *** bug in splay: n not in q *** " ); */ + if (root != prev) { + /*fprintf(stderr, " *** bug in splay: n not in q *** " ); */ abort(); } #endif n->leftlink = left; n->rightlink = right; - if (left != nullptr) + if (left != nullptr) { left->uplink = n; - if (right != nullptr) + } + if (right != nullptr) { right->uplink = n; - q->root = n; + } + root = n; n->uplink = nullptr; +} -} /* splay */ - - -/* Original file: spaux.cpp - - spaux.cpp: This code implements the following operations on an event-set - or priority-queue implemented using splay trees: - - n = sphead( q ) n is the head item in q (not removed). - spdelete( n, q ) n is removed from q. - - In the above, n and np are pointers to single items (type - SPBLK *); q is an event-set (type SPTREE *), - The type definitions for these are taken - from file sptree.h. All of these operations rest on basic - splay tree operations from file sptree.cpp. - - The basic splay tree algorithms were originally presented in: - - Self Adjusting Binary Trees, - by D. D. Sleator and R. E. Tarjan, - Proc. ACM SIGACT Symposium on Theory - of Computing (Boston, Apr 1983) 235-245. - - The operations in this package supplement the operations from - file splay.h to provide support for operations typically needed - on the pending event set in discrete event simulation. See, for - example, - - Introduction to Simula 67, - by Gunther Lamprecht, Vieweg & Sohn, Braucschweig, Wiesbaden, 1981. - (Chapter 14 contains the relevant discussion.) - - Simula Begin, - by Graham M. Birtwistle, et al, Studentlitteratur, Lund, 1979. - (Chapter 9 contains the relevant discussion.) - - Many of the routines in this package use the splay procedure, - for bottom-up splaying of the queue. Consequently, item n in - delete and item np in all operations listed above must be in the - event-set prior to the call or the results will be - unpredictable (eg: chaos will ensue). - - Note that, in all cases, these operations can be replaced with - the corresponding operations formulated for a conventional - lexicographically ordered tree. The versions here all use the - splay operation to ensure the amortized bounds; this usually - leads to a very compact formulation of the operations - themselves, but it may slow the average performance. - - Alternative versions based on simple binary tree operations are - provided (commented out) for head, next, and prev, since these - are frequently used to traverse the entire data structure, and - the cost of traversal is independent of the shape of the - structure, so the extra time taken by splay in this context is - wasted. - - This code was written by: - Douglas W. Jones with assistance from Srinivas R. Sataluri - - Translated to C by David Brower, daveb@rtech.uucp - - Thu Oct 6 12:11:33 PDT 1988 (daveb) Fixed spdeq, which was broken - handling one-node trees. I botched the pascal translation of - a VAR parameter. Changed interface, so callers must also be - corrected to pass the node by address rather than value. - Mon Apr 3 15:18:32 PDT 1989 (daveb) - Apply fix supplied by Mark Moraes to - spdelete(), which dropped core when taking out the last element - in a subtree -- that is, when the right subtree was empty and - the leftlink was also null, it tried to take out the leftlink's - uplink anyway. - */ - -/*---------------- - * - * sphead() -- return the "lowest" element in the tree. - * - * returns a reference to the head event in the event-set q, - * represented as a splay tree; q->root ends up pointing to the head - * event, and the old left branch of q is shortened, as if q had - * been splayed about the head element; this is done by dequeueing - * the head and then making the resulting queue the right son of - * the head returned by spdeq; an alternative is provided which - * avoids splaying but just searches for and returns a pointer to - * the bottom of the left branch - */ -template -SPBLK* sphead(SPTREE* q) { - SPBLK* x; - - /* splay version, good amortized bound */ - x = spdeq(&q->root); - if (x != nullptr) { - x->rightlink = q->root; - x->leftlink = nullptr; - x->uplink = nullptr; - if (q->root != nullptr) - q->root->uplink = x; +template +T* SPTree::first() { + if (empty()) { + return nullptr; } - q->root = x; - - /* alternative version, bad amortized bound, - but faster on the average */ - - return (x); - -} /* sphead */ + T* x = dequeue(); + x->rightlink = root; + x->leftlink = nullptr; + x->uplink = nullptr; + if (root != nullptr) { + root->uplink = x; + } + root = x; -/*---------------- - * - * spdelete() -- Delete node from a tree. - * - * n is deleted from q; the resulting splay tree has been splayed - * around its new root, which is the successor of n - * - */ -template -void spdelete(SPBLK* n, SPTREE* q) { - SPBLK* x; + return x; +} - splay(n, q); - x = spdeq(&q->root->rightlink); +template +void SPTree::remove(T* n) { + splay(n); + T* x = dequeue(&root->rightlink); if (x == nullptr) /* empty right subtree */ { - q->root = q->root->leftlink; - if (q->root) - q->root->uplink = nullptr; + root = root->leftlink; + if (root) { + root->uplink = nullptr; + } } else /* non-empty right subtree */ { x->uplink = nullptr; - x->leftlink = q->root->leftlink; - x->rightlink = q->root->rightlink; - if (x->leftlink != nullptr) + x->leftlink = root->leftlink; + x->rightlink = root->rightlink; + if (x->leftlink != nullptr) { x->leftlink->uplink = x; - if (x->rightlink != nullptr) + } + if (x->rightlink != nullptr) { x->rightlink->uplink = x; - q->root = x; + } + root = x; } +} -} /* spdelete */ - - -/* Original file: spdaveb.cpp - * - * spdaveb.cpp -- daveb's new splay tree functions. - * - * The functions in this file provide an interface that is nearly - * the same as the hash library I swiped from mkmf, allowing - * replacement of one by the other. Hey, it worked for me! - * - * splookup() -- given a key, find a node in a tree. - * spfhead() -- fast (non-splay) find the first node in a tree. - * spscan() -- forward scan tree from the head. - * spfnext() -- non-splaying next. - * - * Written by David Brower, daveb@rtech.uucp 1/88. - */ - - -/*---------------- - * - * splookup() -- given key, find a node in a tree. - * - * Splays the found node to the root. - */ -template -SPBLK* splookup(double key, SPTREE* q) { - SPBLK* n = q->root; +template +T* SPTree::find(double key) { + T* n = root; while (n && key != n->key) { n = key < n->key ? n->leftlink : n->rightlink; } /* reorganize tree around this node */ - if (n != nullptr) - splay(n, q); + if (n != nullptr) { + splay(n); + } - return (n); + return n; } +template +void SPTree::apply_all(void (*f)(const T*, int), T* n) const { + for (T* x = n != nullptr ? n : fast_first(); x != nullptr; x = fast_next(x)) { + std::invoke(f, x, 0); + } +} -/*---------------- - * - * spfhead() -- return the "lowest" element in the tree. - * - * returns a reference to the head event in the event-set q. - * avoids splaying but just searches for and returns a pointer to - * the bottom of the left branch. - */ -template -SPBLK* spfhead(SPTREE* q) { - SPBLK* x; - - if (nullptr != (x = q->root)) - while (x->leftlink != nullptr) - x = x->leftlink; - - return (x); - -} /* spfhead */ - - -/*---------------- - * - * spscan() -- apply a function to nodes in ascending order. - * - * if n is given, start at that node, otherwise start from - * the head. - */ -template -void spscan(void (*f)(const SPBLK*, int), SPBLK* n, SPTREE* q) { - SPBLK* x; +template +T* SPTree::fast_first() const { + if (empty()) { + return nullptr; + } - for (x = n != nullptr ? n : spfhead(q); x != nullptr; x = spfnext(x)) - (*f)(x, 0); + T* x = root; + while (x->leftlink != nullptr) { + x = x->leftlink; + } + return x; } -/*---------------- - * - * spfnext() -- fast return next higer item in the tree, or nullptr. - * - * return the successor of n in q, represented as a splay tree. - * This is a fast (on average) version that does not splay. - */ -template -SPBLK* spfnext(SPBLK* n) { - SPBLK* next; - SPBLK* x; - - /* a long version, avoids splaying for fast average, - * poor amortized bound - */ - - if (n == nullptr) - return (n); - - x = n->rightlink; - if (x != nullptr) { - while (x->leftlink != nullptr) +template +T* SPTree::fast_next(T* n) const { + if (n == nullptr) { + return n; + } + + // If there is a right element, the next element is the smallest item on the most left of this + // right element + if (T* x = n->rightlink; x != nullptr) { + while (x->leftlink != nullptr) { x = x->leftlink; - next = x; - } else /* x == nullptr */ - { - x = n->uplink; - next = nullptr; - while (x != nullptr) { - if (x->leftlink == n) { - next = x; - x = nullptr; - } else { - n = x; - x = n->uplink; - } } + return x; } - return (next); + // Otherwise we have to go up and left + T* next = nullptr; + T* x = n->uplink; + while (x != nullptr) { + if (x->leftlink == n) { + next = x; + x = nullptr; + } else { + n = x; + x = n->uplink; + } + } -} /* spfnext */ + return next; +} diff --git a/src/nrncvode/tqueue.cpp b/src/nrncvode/tqueue.cpp index 8e51035838..9010ae6c43 100644 --- a/src/nrncvode/tqueue.cpp +++ b/src/nrncvode/tqueue.cpp @@ -55,8 +55,7 @@ TQueue::TQueue(TQItemPool* tp, int mkmut) { MUTCONSTRUCT(mkmut) tpool_ = tp; nshift_ = 0; - sptree_ = new SPTREE; - spinit(sptree_); + sptree_ = new SPTree(); binq_ = new BinQ; least_ = 0; @@ -68,7 +67,7 @@ TQueue::TQueue(TQItemPool* tp, int mkmut) { TQueue::~TQueue() { TQItem *q, *q2; - while ((q = spdeq(&sptree_->root)) != nullptr) { + while ((q = sptree_->dequeue()) != nullptr) { deleteitem(q); } delete sptree_; @@ -89,7 +88,7 @@ void TQueue::print() { if (least_) { prnt(least_, 0); } - spscan(prnt, static_cast(nullptr), sptree_); + sptree_->apply_all(prnt, nullptr); for (TQItem* q = binq_->first(); q; q = binq_->next(q)) { prnt(q, 0); } @@ -101,7 +100,7 @@ void TQueue::forall_callback(void (*f)(const TQItem*, int)) { if (least_) { f(least_, 0); } - spscan(f, static_cast(nullptr), sptree_); + sptree_->apply_all(f, nullptr); for (TQItem* q = binq_->first(); q; q = binq_->next(q)) { f(q, 0); } @@ -114,11 +113,11 @@ void TQueue::check(const char* mes) {} // Assume not using bin queue. TQItem* TQueue::second_least(double t) { assert(least_); - TQItem* b = sphead(sptree_); + TQItem* b = sptree_->first(); if (b && b->t_ == t) { return b; } - return 0; + return nullptr; } void TQueue::move_least(double tnew) { @@ -131,11 +130,11 @@ void TQueue::move_least_nolock(double tnew) { TQItem* b = least(); if (b) { b->t_ = tnew; - TQItem* nl = sphead(sptree_); + TQItem* nl = sptree_->first(); if (nl) { if (tnew > nl->t_) { - least_ = spdeq(&sptree_->root); - spenq(b, sptree_); + least_ = sptree_->dequeue(); + sptree_->enqueue(b); } } } @@ -147,14 +146,14 @@ void TQueue::move(TQItem* i, double tnew) { if (i == least_) { move_least_nolock(tnew); } else if (tnew < least_->t_) { - spdelete(i, sptree_); + sptree_->remove(i); i->t_ = tnew; - spenq(least_, sptree_); + sptree_->enqueue(least_); least_ = i; } else { - spdelete(i, sptree_); + sptree_->remove(i); i->t_ = tnew; - spenq(i, sptree_); + sptree_->enqueue(i); } MUTUNLOCK } @@ -167,7 +166,7 @@ void TQueue::statistics() { nrem, nleast); Printf("calls to find=%lu\n", nfind); - Printf("comparisons=%d\n", sptree_->enqcmps); + Printf("comparisons=%d\n", sptree_->get_enqcmps()); #else Printf("Turn on COLLECT_TQueue_STATISTICS_ in tqueue.hpp\n"); #endif @@ -192,11 +191,11 @@ TQItem* TQueue::insert(double t, void* d) { i->cnt_ = -1; if (t < least_t_nolock()) { if (least()) { - spenq(least(), sptree_); + sptree_->enqueue(least()); } least_ = i; } else { - spenq(i, sptree_); + sptree_->enqueue(i); } MUTUNLOCK return i; @@ -223,15 +222,15 @@ void TQueue::remove(TQItem* q) { STAT(nrem); if (q) { if (q == least_) { - if (!spempty(sptree_)) { - least_ = spdeq(&sptree_->root); + if (!sptree_->empty()) { + least_ = sptree_->dequeue(); } else { least_ = nullptr; } } else if (q->cnt_ >= 0) { binq_->remove(q); } else { - spdelete(q, sptree_); + sptree_->remove(q); } tpool_->hpfree(q); } @@ -244,8 +243,8 @@ TQItem* TQueue::atomic_dq(double tt) { if (least_ && least_->t_ <= tt) { q = least_; STAT(nrem); - if (!spempty(sptree_)) { - least_ = spdeq(&sptree_->root); + if (!sptree_->empty()) { + least_ = sptree_->dequeue(); } else { least_ = nullptr; } @@ -262,7 +261,7 @@ TQItem* TQueue::find(double t) { if (t == least_t_nolock()) { q = least(); } else { - q = splookup(t, sptree_); + q = sptree_->find(t); } MUTUNLOCK return (q); diff --git a/src/nrncvode/tqueue.hpp b/src/nrncvode/tqueue.hpp index 4ee6cf23cc..adf45e2464 100644 --- a/src/nrncvode/tqueue.hpp +++ b/src/nrncvode/tqueue.hpp @@ -23,7 +23,7 @@ using TQItemPool = MutexPool; #define COLLECT_TQueue_STATISTICS 1 template -struct SPTREE; +struct SPTree; // helper class for the TQueue (SplayTBinQueue). class BinQ { @@ -133,7 +133,7 @@ class TQueue { } } void move_least_nolock(double tnew); - SPTREE* sptree_; + SPTree* sptree_; BinQ* binq_; TQItem* least_; TQItemPool* tpool_; From 2a4ad63961a60049a6cbf186a97d86b076c2b53e Mon Sep 17 00:00:00 2001 From: Erik Heeren Date: Mon, 8 Apr 2024 11:24:40 +0200 Subject: [PATCH 27/62] Cherry-pick changelog and installer links for 8.2.4 (#2735) --- docs/changelog.md | 52 ++++++++++++++++++++++++++++++++++++----------- docs/index.rst | 21 +++++++++---------- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index ab3b1002c5..0185999a9d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,33 @@ # NEURON 8.2 +## 8.2.4 +_Release Date_ : 08-02-2024 + + +### What's New + +This release brings no new features, just bugfixes and minor improvements. + + +### Bug Fixes +- Python 3.12 compatibility fixes + - replace distutils with setuptools + - fix segfault on exit +- updates to CI + - move from MacOS 11 to MacOS 12 + - add MUSIC + - bugfix for coverage CI +- small bugfix for edge case in RX3D +- unified setup.py +- misc cmake improvements + +### Improvements / Other Changes +- Disabled RXD code in notebook to avoid breaking docs build (see [GitHub Issue #2710](https://github.com/neuronsimulator/nrn/issues/2710)) +- Disabled RXD tests on Windows (see [GitHub Issue #2585](https://github.com/neuronsimulator/nrn/issues/2585)) + + +For the complete list of commits check [GitHub Issue #2700](https://github.com/neuronsimulator/nrn/issues/2700) + ## 8.2.3 _Release Date_ : 15-09-2023 @@ -64,7 +92,7 @@ _Release Date_ : 12-08-2022 - Documentation - added new INCF/CNS 2022 online material (#1932) - updates (dealing with sims, generating movie, modelview, more #1925 ) - - transfer from Yale website (#1867) + - transfer from Yale website (#1867) - nrnmpi_load: drop printf for already loaded lib (#1938) For the complete list of commits, see the list in [GitHub Issue #1944](https://github.com/neuronsimulator/nrn/issues/1944) @@ -76,7 +104,7 @@ _Release Date_ : 01-07-2022 * Allow multiple BEFORE/AFTER blocks of same type in a MOD file. #1722 * Several documentation updates, including randomness in NEURON models #1727, NEURON course exercise sets from 2018 #1735 and publications using NEURON #1819. -* CMake: improved documentation targets. (#1725) +* CMake: improved documentation targets. (#1725) ### Breaking Changes * Support for Python 3.6 was dropped, as it has reached end-of-life (#1733). @@ -87,7 +115,7 @@ _Release Date_ : 01-07-2022 * Declaring STATE variables as GLOBAL is now disallowed. (#1723) ### Deprecations & future changes -* NEURON is in the process of being fully migrated to a `C++` codebase. +* NEURON is in the process of being fully migrated to a `C++` codebase. Starting with next major release `9.0.0`, `MOD` files will be converted to `C++` instead of `C`. This will break compatibility with some legacy MOD files containing VERBATIM blocks and code may have to be updated given that some valid C code is not valid C++. @@ -102,7 +130,7 @@ _Release Date_ : 01-07-2022 ### Improvements / Other Changes * Support for using `mallinfo2()` (#1805) -* HOC domain for Sphinx `5.0.1` +* HOC domain for Sphinx `5.0.1` ### Upgrade Steps * If your MOD files contain VERBATIM blocks you may need to refer to the aforementioned @@ -213,7 +241,7 @@ _Release Date_ : 25-03-2022 * Internal API for saving/restoring 3D voxelization (#1476) * Prevent RxD keeping objects alive (#1270, #1103, #1072) * Improved assignment of 3D voxels to segments (#1149) - + ### Upgrade Steps * Linux wheels are now `manylinux2014`: upgrade your `pip` * Legacy internal `readline` source code is removed: install `readline` on your system @@ -246,7 +274,7 @@ For the complete list of bug fixes, see the list in [GitHub PR #1603](https://gi ### Improvements / Other Changes -- Introduce a Sphinx HOC domain for NEURON documentation +- Introduce a Sphinx HOC domain for NEURON documentation ## 8.0.0 @@ -270,7 +298,7 @@ _Release Date_ : 30-04-2021 - For 3d reaction-diffusion simulations, the voxelization and segment mapping algorithms have been adjusted, especially around the soma. Voxel indices and sometimes counts will change from previous versions. ### Deprecations -- Five functions in the `neuron` module: `neuron.init`, `neuron.run`, `neuron.psection`, `neuron.xopen`, and `neuron.quit`. +- Five functions in the `neuron` module: `neuron.init`, `neuron.run`, `neuron.psection`, `neuron.xopen`, and `neuron.quit`. - Autotools build is deprecated and will be removed in the next release. Use CMake instead. - Python 2 and Python 3.5 support is deprecated and will be removed in the next release. Use `Python >= 3.6` @@ -279,7 +307,7 @@ _Release Date_ : 30-04-2021 For the complete list of bug fixes, see the list on the [GitHub here](https://github.com/neuronsimulator/nrn/issues/1211#issuecomment-826919173). ### Improvements / Other Changes -- Allow for two point (single section) SWC somas +- Allow for two point (single section) SWC somas - GitHub Actions and Azure as primary CI systems. Travis CI removed. - GitHub [Releases](https://github.com/neuronsimulator/nrn/releases) provides full source tarballs, binary installers and python wheels. - Improved testing and CI infrastructure including GPUs @@ -287,18 +315,18 @@ For the complete list of bug fixes, see the list on the [GitHub here](https://gi - Improved integration of CoreNEURON - Support for recent numpy version - Various build improvements on Linux, MacOS and HPC platforms -- Documentation from various repositories is consolidated under `nrn` repository -- New releases via Spack and Easybuild package managers +- Documentation from various repositories is consolidated under `nrn` repository +- New releases via Spack and Easybuild package managers - Fix deadlock when compiling NEURON with AVX-512 - Add backward-cpp for better backtraces -- NEURON_MODULE_OPTIONS environment variable to pass in nrniv options before `neuron import` +- NEURON_MODULE_OPTIONS environment variable to pass in nrniv options before `neuron import` ### Upgrade Steps Existing models should work without any changes. In order to upgrade NEURON version you can: - Use python wheels provided for Linux or Mac OS platform - Use binary installer provided for windows -- Install from source, preferably using CMake build system +- Install from source, preferably using CMake build system - For new version, it's always a good idea to start over from scratch with nrnivmodl (deleting existing directory like `x86_64`) See `Installation` section under [nrn.readthedocs.io/](nrn.readthedocs.io/). In the very rare case that numerical differences exist, check selection of legacy vs modern units. diff --git a/docs/index.rst b/docs/index.rst index 00d8791a9e..06b1a34a9e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,10 +5,10 @@ The NEURON Simulator ==================== NEURON is a simulator for neurons and networks of neurons that runs efficiently on your local machine, in the cloud, or on an HPC. -Build and simulate models using Python, HOC, and/or NEURON's graphical interface. From this page you can watch :ref:`recorded NEURON classes `, +Build and simulate models using Python, HOC, and/or NEURON's graphical interface. From this page you can watch :ref:`recorded NEURON classes `, read the :ref:`Python ` or :ref:`HOC ` programmer's references, `browse the NEURON forum `_, -explore the `source code for over 800 NEURON models on ModelDB `_, +explore the `source code for over 800 NEURON models on ModelDB `_, and more (use the links on the side or search). .. toctree:: @@ -31,7 +31,7 @@ and more (use the links on the side or search). The NEURON forum publications publications-using-neuron - + .. toctree:: @@ -97,8 +97,8 @@ Installation .. code:: pip3 install neuron - - Alternatively, you can use the `PKG installer `_. + + Alternatively, you can use the `PKG installer `_. For troubleshooting, see the `detailed installation instructions `_. @@ -110,19 +110,18 @@ Installation .. code:: pip3 install neuron - For troubleshooting, see the `detailed installation instructions `_. .. tab-item:: Windows - `Download the Windows Installer `_. + `Download the Windows Installer `_. You can also install the Linux wheel via the Windows Subsystem for Linux (WSL). See `instructions `_. For troubleshooting, see the `detailed installation instructions `_. - + .. tab-item:: Cloud On `Google Colab `_ and many other cloud Jupyter providers, you can install @@ -131,10 +130,10 @@ Installation .. code:: !pip install neuron - + NEURON is already installed on `The Neuroscience Gateway `_ and on `EBRAINS `_. - + .. tab-item:: Source code View and suggest changes to the source code at: @@ -168,7 +167,7 @@ Installation nav("userAgent", "Windows"); nav("platform", "Win", "Windows"); nav("oscpu", "Windows"); - + if (osName == "MacOS") { $("#installation input")[0].checked = true; } else if (osName == "Linux") { From 65767ec7b520f6e9284c9853074f12f67de22202 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Mon, 8 Apr 2024 17:53:37 +0200 Subject: [PATCH 28/62] Remove vendored `find_libpython` (#2823) --- cmake/find_libpython.py | 393 ---------------------------------------- 1 file changed, 393 deletions(-) delete mode 100755 cmake/find_libpython.py diff --git a/cmake/find_libpython.py b/cmake/find_libpython.py deleted file mode 100755 index 27568910c9..0000000000 --- a/cmake/find_libpython.py +++ /dev/null @@ -1,393 +0,0 @@ -#!/usr/bin/env python - -""" -Locate libpython associated with this Python executable. -""" - -# https://pypi.org/project/find-libpython/ - -# License -# -# Copyright 2018, Takafumi Arakaki -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -from __future__ import print_function, absolute_import - -from logging import getLogger -import ctypes.util -import functools -import os -import sys -import sysconfig - -logger = getLogger("find_libpython") - -is_windows = os.name == "nt" -is_apple = sys.platform == "darwin" - -SHLIB_SUFFIX = sysconfig.get_config_var("SHLIB_SUFFIX") -if SHLIB_SUFFIX is None: - if is_windows: - SHLIB_SUFFIX = ".dll" - else: - SHLIB_SUFFIX = ".so" -if is_apple: - # sysconfig.get_config_var("SHLIB_SUFFIX") can be ".so" in macOS. - # Let's not use the value from sysconfig. - SHLIB_SUFFIX = ".dylib" - - -def linked_libpython(): - """ - Find the linked libpython using dladdr (in *nix). - - Calling this in Windows always return `None` at the moment. - - Returns - ------- - path : str or None - A path to linked libpython. Return `None` if statically linked. - """ - if is_windows: - return None - return _linked_libpython_unix() - - -class Dl_info(ctypes.Structure): - _fields_ = [ - ("dli_fname", ctypes.c_char_p), - ("dli_fbase", ctypes.c_void_p), - ("dli_sname", ctypes.c_char_p), - ("dli_saddr", ctypes.c_void_p), - ] - - -def _linked_libpython_unix(): - libdl = ctypes.CDLL(ctypes.util.find_library("dl")) - libdl.dladdr.argtypes = [ctypes.c_void_p, ctypes.POINTER(Dl_info)] - libdl.dladdr.restype = ctypes.c_int - - dlinfo = Dl_info() - retcode = libdl.dladdr( - ctypes.cast(ctypes.pythonapi.Py_GetVersion, ctypes.c_void_p), - ctypes.pointer(dlinfo), - ) - if retcode == 0: # means error - return None - path = os.path.realpath(dlinfo.dli_fname.decode()) - if path == os.path.realpath(sys.executable): - return None - return path - - -def library_name(name, suffix=SHLIB_SUFFIX, is_windows=is_windows): - """ - Convert a file basename `name` to a library name (no "lib" and ".so" etc.) - - >>> library_name("libpython3.7m.so") # doctest: +SKIP - 'python3.7m' - >>> library_name("libpython3.7m.so", suffix=".so", is_windows=False) - 'python3.7m' - >>> library_name("libpython3.7m.dylib", suffix=".dylib", is_windows=False) - 'python3.7m' - >>> library_name("python37.dll", suffix=".dll", is_windows=True) - 'python37' - """ - if not is_windows and name.startswith("lib"): - name = name[len("lib") :] - if suffix and name.endswith(suffix): - name = name[: -len(suffix)] - return name - - -def append_truthy(list, item): - if item: - list.append(item) - - -def uniquifying(items): - """ - Yield items while excluding the duplicates and preserving the order. - - >>> list(uniquifying([1, 2, 1, 2, 3])) - [1, 2, 3] - """ - seen = set() - for x in items: - if x not in seen: - yield x - seen.add(x) - - -def uniquified(func): - """Wrap iterator returned from `func` by `uniquifying`.""" - - @functools.wraps(func) - def wrapper(*args, **kwds): - return uniquifying(func(*args, **kwds)) - - return wrapper - - -@uniquified -def candidate_names(suffix=SHLIB_SUFFIX): - """ - Iterate over candidate file names of libpython. - - Yields - ------ - name : str - Candidate name libpython. - """ - LDLIBRARY = sysconfig.get_config_var("LDLIBRARY") - if LDLIBRARY: - yield LDLIBRARY - - LIBRARY = sysconfig.get_config_var("LIBRARY") - if LIBRARY: - yield os.path.splitext(LIBRARY)[0] + suffix - - dlprefix = "" if is_windows else "lib" - sysdata = dict( - v=sys.version_info, - # VERSION is X.Y in Linux/macOS and XY in Windows: - VERSION=( - sysconfig.get_config_var("VERSION") - or "{v.major}.{v.minor}".format(v=sys.version_info) - ), - ABIFLAGS=( - sysconfig.get_config_var("ABIFLAGS") - or sysconfig.get_config_var("abiflags") - or "" - ), - ) - - for stem in [ - "python{VERSION}{ABIFLAGS}".format(**sysdata), - "python{VERSION}".format(**sysdata), - "python{v.major}".format(**sysdata), - "python", - ]: - yield dlprefix + stem + suffix - - -@uniquified -def candidate_paths(suffix=SHLIB_SUFFIX): - """ - Iterate over candidate paths of libpython. - - Yields - ------ - path : str or None - Candidate path to libpython. The path may not be a fullpath - and may not exist. - """ - - yield linked_libpython() - - # List candidates for directories in which libpython may exist - lib_dirs = [] - append_truthy(lib_dirs, sysconfig.get_config_var("LIBPL")) - append_truthy(lib_dirs, sysconfig.get_config_var("srcdir")) - append_truthy(lib_dirs, sysconfig.get_config_var("LIBDIR")) - - # LIBPL seems to be the right config_var to use. It is the one - # used in python-config when shared library is not enabled: - # https://github.com/python/cpython/blob/v3.7.0/Misc/python-config.in#L55-L57 - # - # But we try other places just in case. - - if is_windows: - lib_dirs.append(os.path.join(os.path.dirname(sys.executable))) - else: - lib_dirs.append( - os.path.join(os.path.dirname(os.path.dirname(sys.executable)), "lib") - ) - - # For macOS: - append_truthy(lib_dirs, sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX")) - - lib_dirs.append(sys.exec_prefix) - lib_dirs.append(os.path.join(sys.exec_prefix, "lib")) - - lib_basenames = list(candidate_names(suffix=suffix)) - - for directory in lib_dirs: - for basename in lib_basenames: - yield os.path.join(directory, basename) - - # In macOS and Windows, ctypes.util.find_library returns a full path: - for basename in lib_basenames: - yield ctypes.util.find_library(library_name(basename)) - - -# Possibly useful links: -# * https://packages.ubuntu.com/bionic/amd64/libpython3.6/filelist -# * https://github.com/Valloric/ycmd/issues/518 -# * https://github.com/Valloric/ycmd/pull/519 - - -def normalize_path(path, suffix=SHLIB_SUFFIX, is_apple=is_apple): - """ - Normalize shared library `path` to a real path. - - If `path` is not a full path, `None` is returned. If `path` does - not exists, append `SHLIB_SUFFIX` and check if it exists. - Finally, the path is canonicalized by following the symlinks. - - Parameters - ---------- - path : str ot None - A candidate path to a shared library. - """ - if not path: - return None - if not os.path.isabs(path): - return None - if os.path.exists(path): - return os.path.realpath(path) - if os.path.exists(path + suffix): - return os.path.realpath(path + suffix) - if is_apple: - return normalize_path(_remove_suffix_apple(path), suffix=".so", is_apple=False) - return None - - -def _remove_suffix_apple(path): - """ - Strip off .so or .dylib. - - >>> _remove_suffix_apple("libpython.so") - 'libpython' - >>> _remove_suffix_apple("libpython.dylib") - 'libpython' - >>> _remove_suffix_apple("libpython3.7") - 'libpython3.7' - """ - if path.endswith(".dylib"): - return path[: -len(".dylib")] - if path.endswith(".so"): - return path[: -len(".so")] - return path - - -@uniquified -def finding_libpython(): - """ - Iterate over existing libpython paths. - - The first item is likely to be the best one. - - Yields - ------ - path : str - Existing path to a libpython. - """ - logger.debug("is_windows = %s", is_windows) - logger.debug("is_apple = %s", is_apple) - for path in candidate_paths(): - logger.debug("Candidate: %s", path) - normalized = normalize_path(path) - if normalized: - logger.debug("Found: %s", normalized) - yield normalized - else: - logger.debug("Not found.") - - -def find_libpython(): - """ - Return a path (`str`) to libpython or `None` if not found. - - Parameters - ---------- - path : str or None - Existing path to the (supposedly) correct libpython. - """ - for path in finding_libpython(): - return os.path.realpath(path) - - -def print_all(items): - for x in items: - print(x) - - -def cli_find_libpython(cli_op, verbose): - import logging - - # Importing `logging` module here so that using `logging.debug` - # instead of `logger.debug` outside of this function becomes an - # error. - - if verbose: - logging.basicConfig(format="%(levelname)s %(message)s", level=logging.DEBUG) - - if cli_op == "list-all": - print_all(finding_libpython()) - elif cli_op == "candidate-names": - print_all(candidate_names()) - elif cli_op == "candidate-paths": - print_all(p for p in candidate_paths() if p and os.path.isabs(p)) - else: - path = find_libpython() - if path is None: - return 1 - print(path, end="") - - -def main(args=None): - import argparse - - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "--verbose", "-v", action="store_true", help="Print debugging information." - ) - - group = parser.add_mutually_exclusive_group() - group.add_argument( - "--list-all", - action="store_const", - dest="cli_op", - const="list-all", - help="Print list of all paths found.", - ) - group.add_argument( - "--candidate-names", - action="store_const", - dest="cli_op", - const="candidate-names", - help="Print list of candidate names of libpython.", - ) - group.add_argument( - "--candidate-paths", - action="store_const", - dest="cli_op", - const="candidate-paths", - help="Print list of candidate paths of libpython.", - ) - - ns = parser.parse_args(args) - parser.exit(cli_find_libpython(**vars(ns))) - - -if __name__ == "__main__": - main() From 817fd40953dd2e406a9b6fbe6428af8f84c4418c Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 9 Apr 2024 10:39:04 +0200 Subject: [PATCH 29/62] Use emplace instead of insert in maps (#2819) --- src/parallel/bbsclimpi.cpp | 2 +- src/parallel/bbsdirectmpi.cpp | 2 +- src/parallel/bbslocal.cpp | 2 +- src/parallel/bbslsrv.cpp | 9 ++++----- src/parallel/bbssrv2mpi.cpp | 15 +++++++-------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/parallel/bbsclimpi.cpp b/src/parallel/bbsclimpi.cpp index 5719006960..101949cd83 100644 --- a/src/parallel/bbsclimpi.cpp +++ b/src/parallel/bbsclimpi.cpp @@ -251,7 +251,7 @@ int BBSClient::look_take_result(int pid) { void BBSClient::save_args(int userid) { nrnmpi_ref(sendbuf_); - keepargs_->insert(std::pair(userid, sendbuf_)); + keepargs_->emplace(userid, sendbuf_); post_todo(working_id_); } diff --git a/src/parallel/bbsdirectmpi.cpp b/src/parallel/bbsdirectmpi.cpp index 711f98ade1..ca68f86dfc 100644 --- a/src/parallel/bbsdirectmpi.cpp +++ b/src/parallel/bbsdirectmpi.cpp @@ -246,7 +246,7 @@ int BBSDirect::master_take_result(int pid) { void BBSDirect::save_args(int userid) { nrnmpi_ref(sendbuf_); - keepargs_->insert(std::pair(userid, sendbuf_)); + keepargs_->emplace(userid, sendbuf_); post_todo(working_id_); } diff --git a/src/parallel/bbslocal.cpp b/src/parallel/bbslocal.cpp index acfd8470ea..81911f58df 100644 --- a/src/parallel/bbslocal.cpp +++ b/src/parallel/bbslocal.cpp @@ -199,7 +199,7 @@ int BBSLocal::take_todo() { void BBSLocal::save_args(int userid) { server_->post_todo(working_id_, posting_); - keepargs_->insert(std::pair(userid, posting_)); + keepargs_->emplace(userid, posting_); posting_ = nullptr; } diff --git a/src/parallel/bbslsrv.cpp b/src/parallel/bbslsrv.cpp index d599f8ee23..0dfdbff742 100644 --- a/src/parallel/bbslsrv.cpp +++ b/src/parallel/bbslsrv.cpp @@ -279,8 +279,7 @@ bool BBSLocalServer::look(const char* key, MessageValue** val) { } void BBSLocalServer::post(const char* key, MessageValue* val) { - MessageList::iterator m = messages_->insert( - std::pair(newstr(key), val)); + MessageList::iterator m = messages_->emplace(newstr(key), val); Resource::ref(val); #if debug printf("srvr_post |%s|\n", key); @@ -293,8 +292,8 @@ void BBSLocalServer::post_todo(int parentid, MessageValue* val) { if (p != work_->end()) { w->parent_ = (WorkItem*) ((*p).second); } - work_->insert(std::pair(w->id_, w)); - todo_->insert(w); + work_->emplace(w->id_, w); + todo_->emplace(w); #if debug printf("srvr_post_todo id=%d pid=%d\n", w->id_, parentid); #endif @@ -306,7 +305,7 @@ void BBSLocalServer::post_result(int id, MessageValue* val) { val->ref(); w->val_->unref(); w->val_ = val; - results_->insert(std::pair(w->parent_ ? w->parent_->id_ : 0, w)); + results_->emplace(w->parent_ ? w->parent_->id_ : 0, w); #if debug printf("srvr_post_done id=%d pid=%d\n", id, w->parent_ ? w->parent_->id_ : 0); #endif diff --git a/src/parallel/bbssrv2mpi.cpp b/src/parallel/bbssrv2mpi.cpp index cb5c159a13..3da195fac7 100644 --- a/src/parallel/bbssrv2mpi.cpp +++ b/src/parallel/bbssrv2mpi.cpp @@ -167,7 +167,7 @@ void BBSDirectServer::put_pending(const char* key, int cid) { printf("put_pending |%s| %d\n", key, cid); #endif char* s = newstr(key); - pending_->insert(std::pair(s, cid)); + pending_->emplace(s, cid); } bool BBSDirectServer::take_pending(const char* key, int* cid) { @@ -194,14 +194,13 @@ void BBSDirectServer::post(const char* key, bbsmpibuf* send) { if (take_pending(key, &cid)) { nrnmpi_bbssend(cid, TAKE, send); } else { - MessageList::iterator m = messages_->insert( - std::pair(newstr(key), send)); + MessageList::iterator m = messages_->emplace(newstr(key), send); nrnmpi_ref(send); } } void BBSDirectServer::add_looking_todo(int cid) { - looking_todo_->insert(cid); + looking_todo_->emplace(cid); } void BBSDirectServer::post_todo(int pid, int cid, bbsmpibuf* send) { @@ -214,7 +213,7 @@ void BBSDirectServer::post_todo(int pid, int cid, bbsmpibuf* send) { if (p != work_->end()) { w->parent_ = (WorkItem*) ((*p).second); } - work_->insert(std::pair(w->id_, w)); + work_->emplace(w->id_, w); #if debug printf("work insert %d\n", w->id_); #endif @@ -228,7 +227,7 @@ void BBSDirectServer::post_todo(int pid, int cid, bbsmpibuf* send) { #if debug printf("todo insert\n"); #endif - todo_->insert(w); + todo_->emplace(w); } } @@ -252,7 +251,7 @@ void BBSDirectServer::context(bbsmpibuf* send) { } remaining_context_cnt_ = nrnmpi_numprocs_bbs - 1; for (j = 1; j < nrnmpi_numprocs_bbs; ++j) { - send_context_->insert(j); + send_context_->emplace(j); } LookingToDoList::iterator i = looking_todo_->begin(); while (i != looking_todo_->end()) { @@ -314,7 +313,7 @@ void BBSDirectServer::post_result(int id, bbsmpibuf* send) { nrnmpi_ref(send); nrnmpi_unref(w->buf_); w->buf_ = send; - results_->insert(std::pair(w->parent_ ? w->parent_->id_ : 0, w)); + results_->emplace(w->parent_ ? w->parent_->id_ : 0, w); } int BBSDirectServer::look_take_todo(bbsmpibuf** recv) { From 6bb2781d0f97f07532b0c65cef26f70becc6e879 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Tue, 9 Apr 2024 10:54:34 +0200 Subject: [PATCH 30/62] Remove some unused code (#2824) --- cmake_nrnconf.h.in | 16 ---------------- extend_depcomp.sh | 16 ---------------- src/nrniv/nrnmenu.cpp | 4 ---- src/oc/parse.ypp | 4 ---- 4 files changed, 40 deletions(-) delete mode 100755 extend_depcomp.sh diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 0ee0723bad..105c942071 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -8,11 +8,6 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -#undef CRAY_STACKSEG_END - /* if mac os x */ #undef DARWIN @@ -73,9 +68,6 @@ /* define if using mingw */ #undef MINGW -/* define if using Mike Neubig contributions */ -#undef MikeNeubig - /* where the lib hoc is */ #undef NEURON_DATA_DIR @@ -121,14 +113,6 @@ /* define if RETSIGTYPE(*)(int) is not the prototype for a signal handler */ #undef SIGNAL_CAST -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#undef STACK_DIRECTION - /* Define SUNDIALS data type 'realtype' as 'long double' */ #undef SUNDIALS_DOUBLE_PRECISION diff --git a/extend_depcomp.sh b/extend_depcomp.sh deleted file mode 100755 index 106aca221e..0000000000 --- a/extend_depcomp.sh +++ /dev/null @@ -1,16 +0,0 @@ -if grep -q xlc depcomp ; then - #echo "depcomp already extended to handle xlc. No change to file." - true; -else - sed '/^aix)/,/;;/ { - H - s/\.u/.d/ - s/^aix)/xlc) #following fragment is just like AIX but the extension is .d instead of .u/ - } - /^icc)/ { - x - G - } - ' depcomp > temp - mv temp depcomp -fi diff --git a/src/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index f771e9fb44..25342ae01a 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -485,10 +485,6 @@ static void point_menu(Object* ob, int make_label) { } if (vartype == nrnocCONST) { deflt = true; - -#if defined(MikeNeubig) - deflt = false; -#endif // end of hack } else { deflt = false; } diff --git a/src/oc/parse.ypp b/src/oc/parse.ypp index 70cccbbce0..07f9240e37 100755 --- a/src/oc/parse.ypp +++ b/src/oc/parse.ypp @@ -5,10 +5,6 @@ /* changes as of 2-jan-89 */ /* version 7.2.1 2-jan-89 short form of the for statement */ -#if AIX -#pragma alloca -#endif - #include "hoc.h" #include "hocdec.h" #include "ocmisc.h" From 821f8283a0f34b1049a872157d1728b6ac3b7973 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 9 Apr 2024 13:01:16 +0200 Subject: [PATCH 31/62] Explicitly use const_cast (#2825) --- src/parallel/bbslocal.cpp | 2 +- src/parallel/bbslsrv.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parallel/bbslocal.cpp b/src/parallel/bbslocal.cpp index 81911f58df..8862c80034 100644 --- a/src/parallel/bbslocal.cpp +++ b/src/parallel/bbslocal.cpp @@ -207,7 +207,7 @@ void BBSLocal::return_args(int userid) { KeepArgs::iterator i = keepargs_->find(userid); assert(i != keepargs_->end()); Resource::unref(taking_); - taking_ = (MessageValue*) ((*i).second); + taking_ = const_cast((*i).second); keepargs_->erase(i); taking_->init_unpack(); BBSImpl::return_args(userid); diff --git a/src/parallel/bbslsrv.cpp b/src/parallel/bbslsrv.cpp index 0dfdbff742..47849709e2 100644 --- a/src/parallel/bbslsrv.cpp +++ b/src/parallel/bbslsrv.cpp @@ -245,7 +245,7 @@ BBSLocalServer::~BBSLocalServer() { bool BBSLocalServer::look_take(const char* key, MessageValue** val) { MessageList::iterator m = messages_->find(key); if (m != messages_->end()) { - *val = (MessageValue*) ((*m).second); + *val = const_cast((*m).second); char* s = (char*) ((*m).first); messages_->erase(m); delete[] s; @@ -263,7 +263,7 @@ bool BBSLocalServer::look_take(const char* key, MessageValue** val) { bool BBSLocalServer::look(const char* key, MessageValue** val) { MessageList::iterator m = messages_->find(key); if (m != messages_->end()) { - *val = (MessageValue*) ((*m).second); + *val = const_cast((*m).second); Resource::ref(*val); #if debug printf("srvr_look true |%s|\n", key); From 6de86fc1058e6b3e009f7dc88ccc52c66f602b6f Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 9 Apr 2024 17:47:28 +0200 Subject: [PATCH 32/62] Remove HAVE_TMS code (#2815) --- src/parallel/bbs.cpp | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/src/parallel/bbs.cpp b/src/parallel/bbs.cpp index 95962ccbe2..2a51b20c55 100644 --- a/src/parallel/bbs.cpp +++ b/src/parallel/bbs.cpp @@ -11,16 +11,9 @@ #include "bbsrcli.h" #endif -#if defined(HAVE_TMS) && !NRNMPI -#include -#include -#include -static struct tms tmsbuf, tms_start_; -static clock_t starttime; -#endif - extern int nrn_global_argc; extern char** nrn_global_argv; +extern double nrn_timeus(); bool BBSImpl::is_master_ = false; bool BBSImpl::started_ = false; @@ -132,11 +125,7 @@ double BBSImpl::time() { #if NRNMPI return nrnmpi_wtime(); #else -#ifdef HAVE_TMS - return double(times(&tmsbuf)) / 100.; -#else - return 0.; -#endif + return nrn_timeus(); #endif } @@ -493,18 +482,6 @@ void BBSImpl::done() { return; } done_ = true; -#ifdef HAVE_TMS - clock_t elapsed = times(&tmsbuf) - starttime; - printf("%d tasks in %g seconds. %g seconds waiting for tasks\n", - etaskcnt, - total_exec_time, - worker_take_time); - printf("user=%g sys=%g elapsed=%g %g%%\n", - (double) (tmsbuf.tms_utime - tms_start_.tms_utime) / 100, - (double) (tmsbuf.tms_stime - tms_start_.tms_stime) / 100, - (double) (elapsed) / 100, - 100. * (double) (tmsbuf.tms_utime - tms_start_.tms_utime) / (double) elapsed); -#endif } void BBSImpl::start() { @@ -512,7 +489,4 @@ void BBSImpl::start() { return; } started_ = 1; -#ifdef HAVE_TMS - starttime = times(&tms_start_); -#endif } From 10cead475814b34a7a13e5469e45c87d16835d91 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Tue, 9 Apr 2024 22:10:08 +0200 Subject: [PATCH 33/62] Replace deprecated `pkg_resources` with `importlib` (#2820) --- share/lib/python/scripts/_binwrapper.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/share/lib/python/scripts/_binwrapper.py b/share/lib/python/scripts/_binwrapper.py index 5fd1ca16d1..bd4f200265 100755 --- a/share/lib/python/scripts/_binwrapper.py +++ b/share/lib/python/scripts/_binwrapper.py @@ -7,7 +7,10 @@ import shutil import subprocess import sys -from pkg_resources import working_set +from importlib.metadata import metadata, PackageNotFoundError +from importlib.util import find_spec +from pathlib import Path + from setuptools.command.build_ext import new_compiler from packaging.version import Version from sysconfig import get_config_vars, get_config_var @@ -63,21 +66,14 @@ def _check_cpp_compiler_version(): def _config_exe(exe_name): """Sets the environment to run the real executable (returned)""" + try: + metadata("neuron-nightly") + print("INFO : Using neuron-nightly Package (Developer Version)") + except PackageNotFoundError: + pass - package_name = "neuron" + NRN_PREFIX = str(Path(find_spec("neuron").origin).parent / ".data") - # determine package to find the install location - if "neuron-nightly" in working_set.by_key: - print("INFO : Using neuron-nightly Package (Developer Version)") - package_name = "neuron-nightly" - elif "neuron" in working_set.by_key: - package_name = "neuron" - else: - raise RuntimeError("NEURON package not found! Verify PYTHONPATH") - - NRN_PREFIX = os.path.join( - working_set.by_key[package_name].location, "neuron", ".data" - ) os.environ["NEURONHOME"] = os.path.join(NRN_PREFIX, "share/nrn") os.environ["NRNHOME"] = NRN_PREFIX os.environ["CORENRNHOME"] = NRN_PREFIX From 2b928ad10c3f1b7d3facb06957da42ba6c0e9334 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 10 Apr 2024 11:59:44 +0200 Subject: [PATCH 34/62] Improve COMPARTMENT documentation. (#2771) --- .../modelspec/programmatic/mechanisms/nmodl.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst b/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst index 67010c3a56..dceba6a60e 100644 --- a/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst +++ b/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst @@ -742,16 +742,26 @@ Description: COMPARTMENT volume {state1 state2 . . . } where the STATE s named in the braces have the same compartment volume given by the volume - expression after the COMPARTMENT keyword. + expression after the COMPARTMENT keyword. In case a mechanism involves many compartments whose relative volumes are specified by the elements of an array the syntax is: .. code-block:: none - COMPARTMENT index, volume [ index ] { state1 state2 . . . } + COMPARTMENT index, volume { state1 state2 . . . } - where the STATEs that are diffusing are listed inside the braces. + where the STATEs that are diffusing are listed inside the braces. Note that + STATEs for the diffusing variables must be array variables, and volume + should be the expression to compute the volume for index ``index``. + + The following example states that the volume of the compartment for + ``s[i]`` is ``a[i]*b``. + + .. code-block:: + none + + COMPARTMENT i, a[i]*b { s } LONGITUDINAL_DIFFUSION From 30844e741b8f801fc9879143c2b8dc717d59baeb Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 11 Apr 2024 11:15:05 +0200 Subject: [PATCH 35/62] BBS: use a variant and a std::vector (#2818) --- src/parallel/bbslocal.cpp | 2 +- src/parallel/bbslsrv.cpp | 143 ++++++++---------------- src/parallel/{bbslsrv.h => bbslsrv.hpp} | 29 ++--- 3 files changed, 54 insertions(+), 120 deletions(-) rename src/parallel/{bbslsrv.h => bbslsrv.hpp} (72%) diff --git a/src/parallel/bbslocal.cpp b/src/parallel/bbslocal.cpp index 8862c80034..32549658a0 100644 --- a/src/parallel/bbslocal.cpp +++ b/src/parallel/bbslocal.cpp @@ -2,7 +2,7 @@ #include #include "oc2iv.h" #include "bbslocal.h" -#include "bbslsrv.h" +#include "bbslsrv.hpp" #include #include diff --git a/src/parallel/bbslsrv.cpp b/src/parallel/bbslsrv.cpp index 47849709e2..5d0a1c4f33 100644 --- a/src/parallel/bbslsrv.cpp +++ b/src/parallel/bbslsrv.cpp @@ -1,7 +1,7 @@ #include <../../nrnconf.h> #include #include -#include "bbslsrv.h" +#include "bbslsrv.hpp" #include "oc_ansi.h" #define INT 1 @@ -84,144 +84,93 @@ class WorkList: public std::map {}; class ReadyList: public std::set {}; class ResultList: public std::multimap {}; -MessageItem::MessageItem() { - next_ = nullptr; - type_ = 0; -} - -MessageItem::~MessageItem() { - switch (type_) { - case STRING: - delete[] u.s; - break; - case VECTOR: - delete[] u.pd; - break; - case PICKLE: - delete[] u.s; - break; - } -} - -MessageValue::MessageValue() { - first_ = nullptr; - last_ = nullptr; - unpack_ = nullptr; -} - -MessageValue::~MessageValue() { - MessageItem *mi, *next; - for (mi = first_; mi; mi = next) { - next = mi->next_; - delete mi; - } -} - -MessageItem* MessageValue::link() { - MessageItem* mi = new MessageItem(); - if (last_) { - last_->next_ = mi; - } else { - first_ = mi; - unpack_ = mi; - } - last_ = mi; - return mi; -} - void MessageValue::init_unpack() { - unpack_ = first_; + index_ = 0; } int MessageValue::pkint(int i) { - MessageItem* m = link(); - m->type_ = INT; - m->u.i = i; + args_.emplace_back(i); return 0; } int MessageValue::pkdouble(double x) { - MessageItem* m = link(); - m->type_ = DOUBLE; - m->u.d = x; + args_.emplace_back(x); return 0; } int MessageValue::pkvec(int n, double* x) { - int i; - MessageItem* m = link(); - m->type_ = VECTOR; - m->u.pd = new double[n]; - for (i = 0; i < n; ++i) { - m->u.pd[i] = x[i]; - } + args_.emplace_back(std::vector(x, x + n)); return 0; } int MessageValue::pkstr(const char* str) { - MessageItem* m = link(); - m->type_ = STRING; - m->u.s = new char[strlen(str) + 1]; - strcpy(m->u.s, str); + args_.emplace_back(std::string(str)); return 0; } int MessageValue::pkpickle(const char* bytes, size_t n) { - MessageItem* m = link(); - m->type_ = PICKLE; - m->u.s = new char[n]; - m->size_ = n; - memcpy(m->u.s, bytes, n); + args_.emplace_back(std::vector(bytes, bytes + n)); return 0; } int MessageValue::upkint(int* i) { - if (!unpack_ || unpack_->type_ != INT) { + if (index_ > args_.size()) { return -1; } - *i = unpack_->u.i; - unpack_ = unpack_->next_; - return 0; + if (const auto* val = std::get_if(args_.data() + index_)) { + *i = *val; + ++index_; + return 0; + } + return -1; } int MessageValue::upkdouble(double* d) { - if (!unpack_ || unpack_->type_ != DOUBLE) { - return -1; + const auto& mi = args_.front(); + if (const auto* val = std::get_if(args_.data() + index_)) { + *d = *val; + ++index_; + return 0; } - *d = unpack_->u.d; - unpack_ = unpack_->next_; - return 0; + return -1; } int MessageValue::upkvec(int n, double* d) { - int i; - if (!unpack_ || unpack_->type_ != VECTOR) { - return -1; - } - for (i = 0; i < n; ++i) { - d[i] = unpack_->u.pd[i]; + const auto& mi = args_.front(); + if (const auto* val = std::get_if>(args_.data() + index_)) { + for (std::size_t i = 0; i < n; ++i) { + d[i] = val->at(i); + } + ++index_; + return 0; } - unpack_ = unpack_->next_; - return 0; + return -1; } int MessageValue::upkstr(char* s) { - if (!unpack_ || unpack_->type_ != STRING) { - return -1; + const auto& mi = args_.front(); + if (const auto* val = std::get_if(args_.data() + index_)) { + for (std::size_t i = 0; i < val->size(); ++i) { + s[i] = val->at(i); + } + s[val->size()] = '\0'; + ++index_; + return 0; } - strcpy(s, unpack_->u.s); - unpack_ = unpack_->next_; - return 0; + return -1; } int MessageValue::upkpickle(char* s, size_t* n) { - if (!unpack_ || unpack_->type_ != PICKLE) { - return -1; + const auto& mi = args_.front(); + if (const auto* val = std::get_if>(args_.data() + index_)) { + *n = val->size(); + for (std::size_t i = 0; i < *n; ++i) { + s[i] = val->at(i); + } + ++index_; + return 0; } - *n = unpack_->size_; - memcpy(s, unpack_->u.s, *n); - unpack_ = unpack_->next_; - return 0; + return -1; } BBSLocalServer::BBSLocalServer() { diff --git a/src/parallel/bbslsrv.h b/src/parallel/bbslsrv.hpp similarity index 72% rename from src/parallel/bbslsrv.h rename to src/parallel/bbslsrv.hpp index 0e7a866a5b..ed6f87e68a 100644 --- a/src/parallel/bbslsrv.h +++ b/src/parallel/bbslsrv.hpp @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + #include class MessageList; @@ -7,25 +11,10 @@ class WorkList; class ReadyList; class ResultList; -class MessageItem { - public: - MessageItem(); - virtual ~MessageItem(); - MessageItem* next_; - int type_; - size_t size_; // for pickle type - union { - int i; - double d; - double* pd; - char* s; - } u; -}; +using MessageItem = std::variant, std::vector, std::string>; class MessageValue: public Resource { public: - MessageValue(); - virtual ~MessageValue(); void init_unpack(); // following return 0 if success, -1 if failure int upkint(int*); @@ -41,12 +30,8 @@ class MessageValue: public Resource { int pkpickle(const char*, size_t); private: - MessageItem* link(); - - private: - MessageItem* first_; - MessageItem* last_; - MessageItem* unpack_; + std::vector args_{}; + std::size_t index_{}; }; class BBSLocalServer { From d3d88869246ae587a57f03df6d6011a649274150 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 11 Apr 2024 18:15:00 +0200 Subject: [PATCH 36/62] BBS: Clean execute_helper (#2826) --- src/parallel/ocbbs.cpp | 157 +++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 70 deletions(-) diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 0df1804fdf..e71cb56900 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -1,4 +1,4 @@ -#include <../../nrnconf.h> +#include #include #include "classreg.h" #include "oc2iv.h" @@ -807,7 +807,7 @@ static double alltoall(void*) { ns = vector_capacity(vsrc); double* s = vector_vec(vsrc); if (vector_capacity(vscnt) != np) { - hoc_execerror("size of source counts vector is not nhost", 0); + hoc_execerror("size of source counts vector is not nhost", nullptr); } double* x = vector_vec(vscnt); int* scnt = new int[np]; @@ -818,7 +818,7 @@ static double alltoall(void*) { sdispl[i + 1] = sdispl[i] + scnt[i]; } if (ns != sdispl[np]) { - hoc_execerror("sum of source counts is not the size of the src vector", 0); + hoc_execerror("sum of source counts is not the size of the src vector", nullptr); } Vect* vdest = vector_arg(3); if (nrnmpi_numprocs > 1) { @@ -991,7 +991,7 @@ static double thread_dt(void*) { static double nrncorewrite_argvec(void*) { if (ifarg(2) && !(hoc_is_object_arg(2) && is_vector_arg(2))) { - hoc_execerror("nrnbbcore_write: optional second arg is not a Vector", NULL); + hoc_execerror("nrnbbcore_write: optional second arg is not a Vector", nullptr); } return double(nrncore_write()); } @@ -1013,7 +1013,8 @@ static double print_memory_stats(void*) { static double nrncorewrite_argappend(void*) { if (ifarg(2) && !hoc_is_double_arg(2)) { hoc_execerror( - "nrncore_write: optional second arg is not a number (True or False append flag)", NULL); + "nrncore_write: optional second arg is not a number (True or False append flag)", + nullptr); } return double(nrncore_write()); } @@ -1160,8 +1161,28 @@ void ParallelContext_reg() { class2oc("ParallelContext", cons, destruct, members, nullptr, retobj_members, retstr_members); } +// A BBS message is something to execute. +// This helper execute depending of the style of the message. +// style == 0: +// This is a string that is a hoc statement, execute it with `hoc_obj_run`. +// Return `nullptr`, set `size` argument to 0. +// Not listen to `exec`. +// No arguments. +// style == 1: +// This is a function name as a string followed by a list of arguments. +// Return `nullptr` and set `size` to 0. +// Dry run if `exec` is false. +// style == 2: +// From a template, find a object with an id and inside this object find a member +// with a name as a string. Execute this member with arguments. +// Return `nullptr` and set `size` to 0. +// Dry run if `exec` is false. +// style == 3: +// A python pickle (https://docs.python.org/3/library/pickle.html) followed by arguments. +// Return a string that is of size `size`. +// Dry run if `exec` is false. char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { - char* s; + char* python_pickle; // Used only for style == 3 int subworld = (nrnmpi_numprocs > 1 && nrnmpi_numprocs_bbs < nrnmpi_numprocs_world); int style = upkint(); if (subworld) { @@ -1171,113 +1192,113 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { info[1] = style; nrnmpi_int_broadcast(info, 2, 0); } - char* rs = 0; + char* rs = nullptr; *size = 0; switch (style) { - case 0: - s = upkstr(); + case 0: { + char* statement = upkstr(); if (subworld) { - int size = strlen(s) + 1; + int size = strlen(statement) + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(s, size, 0); + nrnmpi_char_broadcast(statement, size, 0); } - hoc_obj_run(s, nullptr); - delete[] s; - break; + hoc_obj_run(statement, nullptr); + delete[] statement; + } break; default: { -#if 1 - int i, j; size_t npickle; - Symbol* fname = 0; + Symbol* fname = nullptr; Object* ob = nullptr; - char* sarg[20]; // upto 20 argument may be strings - int ns = 0; // number of args that are strings - int narg = 0; // total number of args - if (style == 2) { // object first - s = upkstr(); // template name - i = upkint(); // object index - // printf("template |%s| index=%d\n", s, i); - Symbol* sym = hoc_lookup(s); + std::list sarg; // Store the strings pointer to delete[] them later + // Use a list because, we push pointers of the object into + // the hoc stack + int narg = 0; // total number of args + if (style == 2) { // object first + char* template_name = upkstr(); + int object_index = upkint(); // object index + Symbol* sym = hoc_lookup(template_name); if (sym) { sym = hoc_which_template(sym); } if (!sym) { - hoc_execerror(s, "is not a template"); + hoc_execerror(template_name, "is not a template"); } hoc_Item *q, *ql; ql = sym->u.ctemplate->olist; ITERATE(q, ql) { ob = OBJ(q); - if (ob->index == i) { + if (ob->index == object_index) { break; } ob = nullptr; } if (!ob) { - fprintf(stderr, "%s[%d] is not an Object in this process\n", s, i); - hoc_execerror("ParallelContext execution error", 0); + fprintf(stderr, + "%s[%d] is not an Object in this process\n", + template_name, + object_index); + hoc_execerror("ParallelContext execution error", nullptr); } - delete[] s; - s = upkstr(); - fname = hoc_table_lookup(s, sym->u.ctemplate->symtable); + delete[] template_name; + char* fname_str = upkstr(); + fname = hoc_table_lookup(fname_str, sym->u.ctemplate->symtable); + if (!fname) { + fprintf(stderr, "%s not a function in %s\n", fname_str, hoc_object_name(ob)); + hoc_execerror("ParallelContext execution error", nullptr); + } + delete[] fname_str; if (subworld) { - hoc_execerror("with subworlds, this submit style not implemented", 0); + hoc_execerror("with subworlds, this submit style not implemented", nullptr); } } else if (style == 3) { // Python callable - s = upkpickle(&npickle); + python_pickle = upkpickle(&npickle); if (subworld) { int size = npickle; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(s, size, 0); + nrnmpi_char_broadcast(python_pickle, size, 0); } } else { - s = upkstr(); + char* fname_str = upkstr(); if (subworld) { - int size = strlen(s) + 1; - // printf("%d exec hoc fun size = %d\n", nrnmpi_myid_world, size); + int size = strlen(fname_str) + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(s, size, 0); + nrnmpi_char_broadcast(fname_str, size, 0); } - fname = hoc_lookup(s); - } - // printf("execute helper style %d fname=%s obj=%s\n", style, fname->name, - // hoc_object_name(ob)); - if (style != 3 && !fname) { - fprintf(stderr, "%s not a function in %s\n", s, hoc_object_name(ob)); - hoc_execerror("ParallelContext execution error", 0); + fname = hoc_lookup(fname_str); + if (!fname) { + fprintf(stderr, "%s not a function in %s\n", fname_str, hoc_object_name(ob)); + hoc_execerror("ParallelContext execution error", nullptr); + } + delete[] fname_str; } + int argtypes = upkint(); // first is least signif if (subworld) { // printf("%d exec argtypes = %d\n", nrnmpi_myid_world, argtypes); nrnmpi_int_broadcast(&argtypes, 1, 0); } - for (j = argtypes; (i = j % 5) != 0; j /= 5) { + for (int i = 0, j = argtypes; (i = j % 5) != 0; j /= 5) { ++narg; if (i == 1) { double x = upkdouble(); - // printf("%d arg %d scalar %g\n", nrnmpi_myid_world, narg, x); if (subworld) { nrnmpi_dbl_broadcast(&x, 1, 0); } hoc_pushx(x); } else if (i == 2) { - sarg[ns] = upkstr(); - // printf("arg %d string |%s|\n", narg, sarg[ns]); + sarg.push_back(upkstr()); if (subworld) { - int size = strlen(sarg[ns]) + 1; + int size = strlen(sarg.back()) + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(sarg[ns], size, 0); + nrnmpi_char_broadcast(sarg.back(), size, 0); } - hoc_pushstr(sarg + ns); - ns++; + hoc_pushstr(&(sarg.back())); } else if (i == 3) { - int n; - n = upkint(); + int n = upkint(); if (subworld) { nrnmpi_int_broadcast(&n, 1, 0); } Vect* vec = new Vect(n); - // printf("arg %d vector size=%d\n", narg, n); upkvec(n, vec->data()); if (subworld) { nrnmpi_dbl_broadcast(vec->data(), n, 0); @@ -1285,15 +1306,15 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { hoc_pushobj(vec->temp_objvar()); } else { // PythonObject size_t n; - char* s = upkpickle(&n); + char* pickle = upkpickle(&n); int size = n; if (subworld) { nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(s, size, 0); + nrnmpi_char_broadcast(pickle, size, 0); } assert(neuron::python::methods.pickle2po); - Object* po = neuron::python::methods.pickle2po(s, n); - delete[] s; + Object* po = neuron::python::methods.pickle2po(pickle, n); + delete[] pickle; hoc_pushobj(hoc_temp_objptr(po)); } } @@ -1301,27 +1322,23 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { assert(neuron::python::methods.call_picklef); if (pickle_ret_) { delete[] pickle_ret_; - pickle_ret_ = 0; + pickle_ret_ = nullptr; pickle_ret_size_ = 0; } if (exec) { - rs = neuron::python::methods.call_picklef(s, npickle, narg, size); + rs = neuron::python::methods.call_picklef(python_pickle, npickle, narg, size); } hoc_ac_ = 0.; + delete[] python_pickle; } else { - // printf("%d exec hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, narg); hoc_ac_ = 0.; if (exec) { hoc_ac_ = hoc_call_objfunc(fname, narg, ob); } - // printf("%d exec return from hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, - // narg); } - delete[] s; - for (i = 0; i < ns; ++i) { - delete[] sarg[i]; + for (auto& arg: sarg) { + delete[] arg; } -#endif } break; } return rs; From 0884fd10c13459d800b40b4798d6fb09e882fc6e Mon Sep 17 00:00:00 2001 From: JCGoran Date: Fri, 12 Apr 2024 14:07:08 +0200 Subject: [PATCH 37/62] Update README (#2831) --- CONTRIBUTING.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ad0d7dccaa..8e13be525c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -94,6 +94,10 @@ formatted, indented, documented, and commented. The [Neuron Development Topics](https://neuronsimulator.github.io/nrn/dev/index.html) section of the documentation provides a starting point for understanding NEURON's internals. +### Building NEURON + +To build NEURON, please follow the instructions [here](docs/install/install_instructions.md#installing-source-distributions). + ### Code Formatting Currently we have enabled CMake and Clang code formatting using [cmake-format](https://github.com/cheshirekow/cmake_format) and [clang-format](https://clang.llvm.org/docs/ClangFormat.html). Before submitting a PR, make sure to run cmake-format and clang-format as below: @@ -142,9 +146,6 @@ Or, See [cmake-format](https://github.com/cheshirekow/cmake_format) documentation for details. -make && make format-pr -``` - ## Python Contributions The Python source code is located under `share/lib/python/neuron`. Python unit tests are From 272be5fa13f543d6a6e394e65ba79c1cd31c86e6 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Fri, 12 Apr 2024 10:07:22 -0400 Subject: [PATCH 38/62] Adopt CoreNEURON cell permute into NEURON. (#2598) * nrn and corenrn share src/coreneuron/permute files. #if CORENRN_BUILD used where code fragments differ * Optimization and refactoring of the permutation algorithm (#2617) * external/ringtest tests ParallelContext.optimize_node_order(i) * Unit test for permutation algorithms * Added permute benchmark file * Clearing up more unused code in NEURON and added implementations for reverse_permute * Improve return values of new functions based on C++ core guidelines * Windows has no std::aligned_alloc. There is an _aligned_alloc, but that must be paired with _aligned_free. cannot std::swap if one is malloc and other is new --------- Co-authored-by: Ioannis Magkanaris Co-authored-by: Pramod Kumbhar --- CMakeLists.txt | 4 + cmake/NeuronFileLists.cmake | 10 + .../modelspec/programmatic/network/parcon.rst | 25 +++ src/coreneuron/CMakeLists.txt | 3 + src/coreneuron/network/tnode.hpp | 8 +- src/coreneuron/permute/balance.cpp | 9 + src/coreneuron/permute/cellorder.cpp | 185 ++++++++++++++++-- src/coreneuron/permute/cellorder.hpp | 18 ++ src/coreneuron/permute/cellorder1.cpp | 28 ++- src/coreneuron/permute/cellorder2.cpp | 13 +- src/coreneuron/permute/node_permute.cpp | 65 ++++++ src/coreneuron/permute/node_permute.h | 20 ++ src/coreneuron/utils/lpt.cpp | 7 +- src/coreneuron/utils/memory.h | 23 +++ src/node_order_optim/README | 26 +++ src/node_order_optim/node_order_optim.h | 27 +++ src/node_order_optim/permute_utils.hpp | 37 ++++ src/nrniv/CMakeLists.txt | 1 + src/nrnoc/fadvance.cpp | 7 +- src/nrnoc/treeset.cpp | 32 +++ src/parallel/ocbbs.cpp | 10 + test/CMakeLists.txt | 1 + test/external/CMakeLists.txt | 2 +- test/external/ringtest/CMakeLists.txt | 14 ++ test/hoctests/tests/test_nrniv-launch.py | 1 + .../hoctests/tests/test_optim_node_order.json | 86 ++++++++ test/hoctests/tests/test_optim_node_order.py | 95 +++++++++ .../node_order_optim/permutations.cpp | 30 +++ 28 files changed, 763 insertions(+), 24 deletions(-) create mode 100644 src/node_order_optim/README create mode 100644 src/node_order_optim/node_order_optim.h create mode 100644 src/node_order_optim/permute_utils.hpp create mode 100644 test/hoctests/tests/test_optim_node_order.json create mode 100644 test/hoctests/tests/test_optim_node_order.py create mode 100644 test/unit_tests/node_order_optim/permutations.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ef953d55ff..d5372ac5d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -444,6 +444,10 @@ if(NRN_ENABLE_THREADS) list(APPEND NRN_COMPILE_DEFS NRN_ENABLE_THREADS) endif() +# Some files are shared by NEURON and CoreNEURON and use #if CORENRN_BUILD to distinguish between +# which build is occurring. +list(APPEND NRN_COMPILE_DEFS CORENRN_BUILD=0) + # ============================================================================= # Profiler/Instrumentation Options # ============================================================================= diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 9141aa4562..fe41a53a55 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -259,6 +259,12 @@ set(NRNIV_FILE_LIST symdir.cpp vrecord.cpp) +# ============================================================================= +# Files from coreneuron/permute that get compiled also for NEURON +# ============================================================================= +set(NODEORDEROPTIM_FILE_LIST balance.cpp cellorder.cpp cellorder1.cpp cellorder2.cpp + node_permute.cpp) + # ============================================================================= # Files in nrncvode directory # ============================================================================= @@ -434,6 +440,7 @@ set(NRN_OC_SRC_DIR ${PROJECT_SOURCE_DIR}/src/oc) set(NRN_NRNOC_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nrnoc) set(NRN_NRNOC_BUILD_DIR ${PROJECT_BINARY_DIR}/src/nrnoc) set(NRN_IVOC_SRC_DIR ${PROJECT_SOURCE_DIR}/src/ivoc) +set(NRN_NODEORDEROPTIM_SRC_DIR ${PROJECT_SOURCE_DIR}/src/coreneuron/permute) set(NRN_NRNCVODE_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nrncvode) set(NRN_NRNIV_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nrniv) set(NRN_MODLUNIT_SRC_DIR ${PROJECT_SOURCE_DIR}/src/modlunit) @@ -448,6 +455,9 @@ nrn_create_file_list(NRN_OC_SRC_FILES ${NRN_OC_SRC_DIR} ${OC_FILE_LIST}) nrn_create_file_list(NRN_NRNOC_SRC_FILES ${NRN_NRNOC_SRC_DIR} ${NRNOC_FILE_LIST}) nrn_create_file_list(NRN_NRNOC_SRC_FILES ${NRN_NRNOC_BUILD_DIR} ${NRNOC_GENERATED_FILE_LIST}) nrn_create_file_list(NRN_IVOC_SRC_FILES ${NRN_IVOC_SRC_DIR} ${IVOC_FILE_LIST}) +nrn_create_file_list(NRN_NODEORDEROPTIM_SRC_FILES ${NRN_NODEORDEROPTIM_SRC_DIR} + ${NODEORDEROPTIM_FILE_LIST}) +list(APPEND NRN_NODEORDEROPTIM_SRC_FILES ${PROJECT_SOURCE_DIR}/src/coreneuron/utils/lpt.cpp) nrn_create_file_list(NRN_NRNCVODE_SRC_FILES ${NRN_NRNCVODE_SRC_DIR} ${NRNCVODE_FILE_LIST}) nrn_create_file_list(NRN_NRNIV_SRC_FILES ${NRN_NRNIV_SRC_DIR} ${NRNIV_FILE_LIST}) nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/nrniv diff --git a/docs/python/modelspec/programmatic/network/parcon.rst b/docs/python/modelspec/programmatic/network/parcon.rst index 4fd8d22f0e..e5970af16a 100755 --- a/docs/python/modelspec/programmatic/network/parcon.rst +++ b/docs/python/modelspec/programmatic/network/parcon.rst @@ -3331,6 +3331,31 @@ Parallel Transfer ---- +.. method:: ParallelContext.optimize_node_order + + Syntax: + ``i= pc.optimize_node_order(i)`` + + Description: + Choose a node order (permutation) of data that + may improve memory latency and bandwidth utilization for gaussian + elmination. + Returns the node order (0-2) chosen (or currently in effect if no argument). + + 0. Nodes of a cell are adjacent. (Though all root nodes are adjacent + at the beginning of each thread's node list.) Default. + 1. Cells are interleaved, corresponding nodes of identical cells + are adjacent. Order of a given cell same as permutation 0. + 2. Depth first ordering. First, cell roots, then nodes + connecting to roots, etc. An attempt is made to order so that if + nodes are adjacent, then their parent nodes are also adjacent. + Note that 1 and 2 are identical ordering if all cells are indentical. + + Adopts the permutation and gaussian elimination methods of + CoreNEURON that were specified by the cell_permute=.. argument. + +---- + .. method:: ParallelContext.prcellstate Syntax: diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index 28b8711f39..d0a8c42e84 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -162,6 +162,9 @@ check_include_files(malloc.h have_malloc_h) if(have_malloc_h) list(APPEND CORENRN_COMPILE_DEFS HAVE_MALLOC_H) endif() +# Code incompletely shared with NEURON via #if CORENRN_BUILD fragments. NRN and CORENEURON builds +# sometimes compile the same few files but, for example, with different name spaces. +list(APPEND CORENRN_COMPILE_DEFS CORENRN_BUILD=1) # ============================================================================= # Build option specific compiler flags diff --git a/src/coreneuron/network/tnode.hpp b/src/coreneuron/network/tnode.hpp index 9f85651e7c..d6448480fa 100644 --- a/src/coreneuron/network/tnode.hpp +++ b/src/coreneuron/network/tnode.hpp @@ -11,7 +11,11 @@ #include // experiment with ordering strategies for Tree Nodes +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif class TNode; using VecTNode = std::vector; @@ -63,10 +67,10 @@ size_t level_from_root(VecTNode&); * * The main steps are the following: * 1. warp_balance function creates balanced groups of cells. - * 2. The compartments/tree nodes populate the groups vector (VVVTN) based on their groudindex and + * 2. The compartments/tree nodes populate the groups vector (VVVTN) based on their groupindex and * their level (see level_from_root). * 3. The analyze() & question2() functions (operating per group) make sure that each cell is still - * a tree (treenode_order) and that the dependent nodes belong to separate warps. + * a tree (treenode_order) and that the nodes with same parents belong to separate warps. */ void group_order2(VecTNode&, size_t groupsize, size_t ncell); size_t dist2child(TNode* nd); diff --git a/src/coreneuron/permute/balance.cpp b/src/coreneuron/permute/balance.cpp index 4aca6c46e3..efecf1fb14 100644 --- a/src/coreneuron/permute/balance.cpp +++ b/src/coreneuron/permute/balance.cpp @@ -15,12 +15,21 @@ // few holes in warp filling. I.e., ncycle = ncompart/warpsize #include +#include +#if CORENRN_BUILD #include "coreneuron/nrnconf.h" +#endif + #include "coreneuron/network/tnode.hpp" #include "coreneuron/utils/lpt.hpp" +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif + int cellorder_nwarp = 0; // 0 means do not balance // ordering by warp, then old order diff --git a/src/coreneuron/permute/cellorder.cpp b/src/coreneuron/permute/cellorder.cpp index 30d3143b06..d8be359409 100644 --- a/src/coreneuron/permute/cellorder.cpp +++ b/src/coreneuron/permute/cellorder.cpp @@ -5,16 +5,28 @@ # See top-level LICENSE file for details. # ============================================================================= */ +#include +#include +#if CORENRN_BUILD #include "coreneuron/nrnconf.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/utils/nrn_assert.h" +#include "coreneuron/apps/corenrn_parameters.hpp" +#else +#include "nrnoc/multicore.h" +#include "nrnoc/nrn_ansi.h" +#include "nrnoc/nrniv_mf.h" +#include "nrnoc/section.h" +#include "oc/nrnassrt.h" +#include "node_order_optim/permute_utils.hpp" +#endif + #include "coreneuron/permute/cellorder.hpp" #include "coreneuron/network/tnode.hpp" #include "coreneuron/utils/lpt.hpp" #include "coreneuron/utils/memory.h" #include "coreneuron/utils/offload.hpp" -#include "coreneuron/apps/corenrn_parameters.hpp" #include "coreneuron/permute/node_permute.h" // for print_quality @@ -22,9 +34,11 @@ #include #endif -#include - +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif int interleave_permute_type; InterleaveInfo* interleave_info; // nrn_nthread array @@ -108,6 +122,11 @@ void destroy_interleave_info() { // more precise visualization of the warp quality // can be called after admin2 static void print_quality2(int iwarp, InterleaveInfo& ii, int* p) { + // '.' p[i] = p[i-1] + 1 (but first of cacheline is 'o') + // 'o' p[i] != p[i-1] + 1 and not a child race + // 'r' p[i] = p[i-1] + 1 and race + // 'R' p[1] != p[i-1] + 1 and race + // 'X' core is unused int pc = (iwarp == 0); // print warp 0 pc = 0; // turn off printing int nodebegin = ii.lastnode[iwarp]; @@ -116,12 +135,11 @@ static void print_quality2(int iwarp, InterleaveInfo& ii, int* p) { int inode = nodebegin; - size_t nn = 0; // number of nodes in warp. '.' - size_t nx = 0; // number of idle cores on all cycles. 'X' - size_t ncacheline = 0; - ; // number of parent memory cacheline accesses. - // assmue warpsize is max number in a cachline so all o - size_t ncr = 0; // number of child race. nchild-1 of same parent in same cycle + size_t nn = 0; // number of nodes in warp. '.oRr' + size_t nx = 0; // number of idle cores on all cycles. 'X' + size_t ncacheline = 0; // number of parent memory cacheline accesses. + // assume warpsize is max number in a cacheline so all o + size_t ncr = 0; // number of child race. nchild-1 of same parent in same cycle for (int icycle = 0; icycle < ncycle; ++icycle) { int s = stride[icycle]; @@ -285,10 +303,53 @@ static void warp_balance(int ith, InterleaveInfo& ii) { #endif } +#if !CORENRN_BUILD +static void prnode(const char* mes, NrnThread& nt) { + printf("%s nrnthread %d node info\n", mes, nt.id); + for (int i = 0; i < nt.end; ++i) { + printf( + " _v_node[%2d]->v_node_index=%2d %p" + " _v_parent[%2d]->v_node_index=%2d parent[%2d]=%2d\n", + i, + nt._v_node[i]->v_node_index, + nt._v_node[i], + i, + nt._v_parent[i] ? nt._v_parent[i]->v_node_index : -1, + i, + nt._v_parent_index[i]); + } + for (auto tml = nt.tml; tml; tml = tml->next) { + Memb_list* ml = tml->ml; + printf(" %s %d\n", memb_func[tml->index].sym->name, ml->nodecount); + for (int i = 0; i < ml->nodecount; ++i) { + printf(" %2d ndindex=%2d nd=%p [%2d] pdata=%p prop=%p\n", + i, + ml->nodeindices[i], + ml->nodelist[i], + ml->nodelist[i]->v_node_index, + ml->pdata[i], + ml->prop[i]); + } + } +} + +int nrn_optimize_node_order(int type) { + if (type != interleave_permute_type) { + tree_changed = 1; // calls setup_topology. v_stucture_change = 1 may be better. + } + interleave_permute_type = type; + return type; +} +#endif // !CORENRN_BUILD + +#if CORENRN_BUILD int* interleave_order(int ith, int ncell, int nnode, int* parent) { +#else +std::vector interleave_order(int ith, int ncell, int nnode, int* parent) { +#endif // return if there are no nodes to permute if (nnode <= 0) - return nullptr; + return {}; // ensure parent of root = -1 for (int i = 0; i < ncell; ++i) { @@ -300,7 +361,7 @@ int* interleave_order(int ith, int ncell, int nnode, int* parent) { int nwarp = 0, nstride = 0, *stride = nullptr, *firstnode = nullptr; int *lastnode = nullptr, *cellsize = nullptr, *stridedispl = nullptr; - int* order = node_order( + auto order = node_order( ncell, nnode, parent, nwarp, nstride, stride, firstnode, lastnode, cellsize, stridedispl); if (interleave_info) { @@ -327,12 +388,21 @@ int* interleave_order(int ith, int ncell, int nnode, int* parent) { } if (ith == 0) { // needed for print_quality[12] and done once here to save time +#if CORENRN_BUILD int* p = new int[nnode]; +#else + std::vector p(nnode); +#endif for (int i = 0; i < nnode; ++i) { p[i] = parent[i]; } +#if CORENRN_BUILD permute_ptr(p, nnode, order); node_permute(p, nnode, order); +#else + forward_permute(p, order); + update_parent_index(p.data(), p.size(), order); +#endif ii.nnode = new size_t[nwarp]; ii.ncycle = new size_t[nwarp]; @@ -341,13 +411,23 @@ int* interleave_order(int ith, int ncell, int nnode, int* parent) { ii.child_race = new size_t[nwarp]; for (int i = 0; i < nwarp; ++i) { if (interleave_permute_type == 1) { +#if CORENRN_BUILD print_quality1(i, interleave_info[ith], ncell, p); +#else + print_quality1(i, interleave_info[ith], ncell, p.data()); +#endif } if (interleave_permute_type == 2) { +#if CORENRN_BUILD print_quality2(i, interleave_info[ith], p); +#else + print_quality2(i, interleave_info[ith], p.data()); +#endif } } +#if CORENRN_BUILD delete[] p; +#endif warp_balance(ith, interleave_info[ith]); } } @@ -355,6 +435,46 @@ int* interleave_order(int ith, int ncell, int nnode, int* parent) { return order; } +#if !CORENRN_BUILD +void nrn_permute_node_order() { + if (!interleave_permute_type) { + return; + } + // printf("enter nrn_permute_node_order\n"); + destroy_interleave_info(); + create_interleave_info(); + for (int tid = 0; tid < nrn_nthread; ++tid) { + auto& nt = nrn_threads[tid]; + auto perm = interleave_order(tid, nt.ncell, nt.end, nt._v_parent_index); + auto p = inverse_permute_vector(perm); +#if 0 + for (int i = 0; i < nt.end; ++i) { + int x = nt._v_parent_index[p[i]]; + int par = x >= 0 ? perm[x] : -1; + printf("%2d <- %2d parent=%2d\n", i, p[i], par); + } +#endif + // prnode("before perm", nt); + forward_permute(nt._v_node, nt.end, p); + forward_permute(nt._v_parent, nt.end, p); + forward_permute(nt._v_parent_index, nt.end, p); + update_parent_index(nt._v_parent_index, nt.end, perm); + for (int i = 0; i < nt.end; ++i) { + nt._v_node[i]->v_node_index = i; + } + for (auto tml = nt.tml; tml; tml = tml->next) { + Memb_list* ml = tml->ml; + for (int i = 0; i < ml->nodecount; ++i) { + ml->nodeindices[i] = perm[ml->nodeindices[i]]; + } + sort_ml(ml); // all fields in increasing nodeindex order + } + // prnode("after perm", nt); + } + // printf("leave nrn_permute_node_order\n"); +} +#endif // !CORENRN_BUILD + #if INTERLEAVE_DEBUG // only the cell per core style static int** cell_indices_debug(NrnThread& nt, InterleaveInfo& ii) { int ncell = nt.ncell; @@ -422,11 +542,19 @@ void mk_cell_indices() { } #endif // INTERLEAVE_DEBUG -#define GPU_V(i) nt->_actual_v[i] -#define GPU_A(i) nt->_actual_a[i] -#define GPU_B(i) nt->_actual_b[i] -#define GPU_D(i) nt->_actual_d[i] -#define GPU_RHS(i) nt->_actual_rhs[i] +#if CORENRN_BUILD +#define GPU_V(i) nt->_actual_v[i] +#define GPU_A(i) nt->_actual_a[i] +#define GPU_B(i) nt->_actual_b[i] +#define GPU_D(i) nt->_actual_d[i] +#define GPU_RHS(i) nt->_actual_rhs[i] +#else +#define GPU_V(i) vec_v[i] +#define GPU_A(i) vec_a[i] +#define GPU_B(i) vec_b[i] +#define GPU_D(i) vec_d[i] +#define GPU_RHS(i) vec_rhs[i] +#endif #define GPU_PARENT(i) nt->_v_parent_index[i] // How does the interleaved permutation with stride get used in @@ -439,6 +567,12 @@ static void triang_interleaved(NrnThread* nt, int nstride, int* stride, int* lastnode) { +#if !CORENRN_BUILD + auto* const vec_a = nt->node_a_storage(); + auto* const vec_b = nt->node_b_storage(); + auto* const vec_d = nt->node_d_storage(); + auto* const vec_rhs = nt->node_rhs_storage(); +#endif int i = lastnode[icell]; for (int istride = nstride - 1; istride >= 0; --istride) { if (istride < icellsize) { // only first icellsize strides matter @@ -462,6 +596,12 @@ static void bksub_interleaved(NrnThread* nt, int /* nstride */, int* stride, int* firstnode) { +#if !CORENRN_BUILD + auto* const vec_a = nt->node_a_storage(); + auto* const vec_b = nt->node_b_storage(); + auto* const vec_d = nt->node_d_storage(); + auto* const vec_rhs = nt->node_rhs_storage(); +#endif int i = firstnode[icell]; GPU_RHS(icell) /= GPU_D(icell); // the root for (int istride = 0; istride < icellsize; ++istride) { @@ -483,6 +623,12 @@ static void solve_interleaved2_loop_body(NrnThread* nt, int* stridedispl, int* rootbegin, int* nodebegin) { +#if !CORENRN_BUILD + auto* const vec_a = nt->node_a_storage(); + auto* const vec_b = nt->node_b_storage(); + auto* const vec_d = nt->node_d_storage(); + auto* const vec_rhs = nt->node_rhs_storage(); +#endif int iwarp = icore / warpsize; // figure out the >> value int ic = icore & (warpsize - 1); // figure out the & mask int ncycle = ncycles[iwarp]; @@ -564,7 +710,7 @@ static void solve_interleaved2_loop_body(NrnThread* nt, /** * \brief Solve Hines matrices/cells with compartment-based granularity. * - * The node ordering/permuation guarantees cell interleaving (as much coalesced memory access as + * The node ordering/permutation guarantees cell interleaving (as much coalesced memory access as * possible) and balanced warps (through the use of lpt algorithm to define the groups/warps). Every * warp deals with a group of cells, therefore multiple compartments (finer level of parallelism). */ @@ -593,7 +739,12 @@ void solve_interleaved2(int ith) { int nstride = stridedispl[nwarp]; #endif // nvc++/22.3 does not respect an if clause inside nrn_pragma_omp... +#if CORENRN_BUILD if (nt->compute_gpu) { +#else + // bad clang-format + if (0) { // nt->compute_gpu) { +#endif /* If we compare this loop with the one from cellorder.cu (CUDA version), we will * understand that the parallelism here is exposed in steps, while in the CUDA version * all the parallelism is exposed from the very beginning of the loop. In more details, diff --git a/src/coreneuron/permute/cellorder.hpp b/src/coreneuron/permute/cellorder.hpp index fe2f2f84e5..353d9dd077 100644 --- a/src/coreneuron/permute/cellorder.hpp +++ b/src/coreneuron/permute/cellorder.hpp @@ -10,7 +10,13 @@ #include "coreneuron/utils/memory.h" #include +#include + +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif /** * \brief Function that performs the permutation of the cells such that the @@ -23,11 +29,16 @@ namespace coreneuron { * * \return int* order, interleaved order of the cells */ +#if CORENRN_BUILD int* interleave_order(int ith, int ncell, int nnode, int* parent); +#else +std::vector interleave_order(int ith, int ncell, int nnode, int* parent); +#endif void create_interleave_info(); void destroy_interleave_info(); +#if CORENRN_BUILD /** * * \brief Solve the Hines matrices based on the interleave_permute_type (1 or 2). @@ -37,8 +48,10 @@ void destroy_interleave_info(); * is solved by multiple execution threads (with coalesced memory access as well) */ extern void solve_interleaved(int ith); +#endif class InterleaveInfo; // forward declaration +#if CORENRN_BUILD /** * * \brief CUDA branch of the solve_interleaved with interleave_permute_type == 2. @@ -46,6 +59,7 @@ class InterleaveInfo; // forward declaration * This branch is activated in runtime with the --cuda-interface CLI flag */ void solve_interleaved2_launcher(NrnThread* nt, InterleaveInfo* info, int ncore, void* stream); +#endif class InterleaveInfo: public MemoryManaged { public: @@ -95,7 +109,11 @@ class InterleaveInfo: public MemoryManaged { * \param stridedispl * \return int* : a permutation of length nnode */ +#if CORENRN_BUILD int* node_order(int ncell, +#else +std::vector node_order(int ncell, +#endif int nnode, int* parents, int& nwarp, diff --git a/src/coreneuron/permute/cellorder1.cpp b/src/coreneuron/permute/cellorder1.cpp index d016d96666..4c18226f52 100644 --- a/src/coreneuron/permute/cellorder1.cpp +++ b/src/coreneuron/permute/cellorder1.cpp @@ -12,16 +12,34 @@ #include #include +#if CORENRN_BUILD #include "coreneuron/utils/nrn_assert.h" +#else +#include "oc/nrnassrt.h" +#endif + #include "coreneuron/permute/cellorder.hpp" #include "coreneuron/network/tnode.hpp" // just for interleave_permute_type +#if CORENRN_BUILD #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/memory.h" +#else +#include "node_order_optim/node_order_optim.h" +#endif +#if !CORENRN_BUILD && NRN_DEBUG +#undef CORENRN_DEBUG +#define CORENRN_DEBUG NRN_DEBUG +#endif +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif + static size_t groupsize = 32; /** @@ -127,7 +145,7 @@ static void quality(VecTNode& nodevec, size_t max = 32) { size_t ip = nodevec[i]->parent->nodevec_index; // i%max == 0 means that if we start a warp with 8 and then have 32 // the 32 is broken into 24 and 8. (modify if the arrangement during - // gaussian elimination becomes more sophisticated.( + // gaussian elimination becomes more sophisticated.) if (ip == ip_last + 1 && i % max != 0) { // contiguous qcnt += 1; } else { @@ -297,7 +315,11 @@ static void ident_statistic(VecTNode& nodevec, size_t ncell) { } #undef MSS +#if CORENRN_BUILD int* node_order(int ncell, +#else +std::vector node_order(int ncell, +#endif int nnode, int* parent, int& nwarp, @@ -339,7 +361,11 @@ int* node_order(int ncell, quality(nodevec); // the permutation +#if CORENRN_BUILD int* nodeorder = new int[nnode]; +#else + std::vector nodeorder(nnode); +#endif for (int i = 0; i < nnode; ++i) { TNode& nd = *nodevec[i]; nodeorder[nd.nodeindex] = i; diff --git a/src/coreneuron/permute/cellorder2.cpp b/src/coreneuron/permute/cellorder2.cpp index b70958a189..5d696ee628 100644 --- a/src/coreneuron/permute/cellorder2.cpp +++ b/src/coreneuron/permute/cellorder2.cpp @@ -13,15 +13,26 @@ #include #include +#if CORENRN_BUILD #include "coreneuron/utils/nrn_assert.h" +#include "coreneuron/nrniv/nrniv_decl.h" +#else +#include "oc/nrnassrt.h" +#endif + #include "coreneuron/permute/cellorder.hpp" #include "coreneuron/network/tnode.hpp" -#include "coreneuron/nrniv/nrniv_decl.h" + // experiment starting with identical cell ordering // groupindex aleady defined that keeps identical cells together // begin with leaf to root ordering +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif + using VTN = VecTNode; // level of nodes using VVTN = std::vector; // group of levels using VVVTN = std::vector; // groups diff --git a/src/coreneuron/permute/node_permute.cpp b/src/coreneuron/permute/node_permute.cpp index 6ef211b267..d79d3ce44a 100644 --- a/src/coreneuron/permute/node_permute.cpp +++ b/src/coreneuron/permute/node_permute.cpp @@ -88,12 +88,37 @@ so pdata_m(k, isz) = inew + data_t #include #include +#if CORENRN_BUILD #include "coreneuron/sim/multicore.hpp" #include "coreneuron/io/nrn_setup.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/nrn_assert.h" #include "coreneuron/coreneuron.hpp" +#else +#include "nrnoc/multicore.h" +#include "oc/nrnassrt.h" +#include "node_order_optim/permute_utils.hpp" +#endif + +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif + +#if !CORENRN_BUILD +static int nrn_soa_padded_size(int cnt, int layout) { + assert(layout == 1); + return cnt; +} +static int nrn_i_layout(int icnt, int cnt, int isz, int sz, int layout) { + assert(isz == 0); + assert(sz == 1); + assert(layout == 1); + return icnt; +} +#endif // !CORENRN_BUILD + template void permute(T* data, int cnt, int sz, int layout, int* p) { // data(p[icnt], isz) <- data(icnt, isz) @@ -107,9 +132,11 @@ void permute(T* data, int cnt, int sz, int layout, int* p) { return; } +#if CORENRN_BUILD if (layout == Layout::SoA) { // for SoA, n might be larger due to cnt padding n = nrn_soa_padded_size(cnt, layout) * sz; } +#endif T* data_orig = new T[n]; for (int i = 0; i < n; ++i) { @@ -157,6 +184,7 @@ static void invert_permute(int* p, int n) { // full_search: helper for type_of_ntdata. Return mech type for nt._data[i]. // Update type_hints. +#if CORENRN_BUILD static std::vector type_hints; static int full_search(NrnThread& nt, double* pd) { @@ -208,7 +236,9 @@ int type_of_ntdata(NrnThread& nt, int i, bool reset) { // after the last type_hints return full_search(nt, pd); } +#endif // CORENRN_BUILD +#if CORENRN_BUILD static void update_pdata_values(Memb_list* ml, int type, NrnThread& nt) { // assumes AoS to SoA transformation already made since we are using // nrn_i_layout to determine indices into both ml->pdata and into target data @@ -342,6 +372,18 @@ void node_permute(int* vec, int n, int* permute) { } } +#else // not CORENRN_BUILD + +void update_parent_index(int* vec, int vec_size, const std::vector& permute) { + for (int i = 0; i < vec_size; ++i) { + if (vec[i] >= 0) { + vec[i] = permute[vec[i]]; + } + } +} + +#endif // not CORENRN_BUILD + void permute_ptr(int* vec, int n, int* p) { permute(vec, n, 1, 1, p); } @@ -350,6 +392,7 @@ void permute_data(double* vec, int n, int* p) { permute(vec, n, 1, 1, p); } +#if CORENRN_BUILD void permute_ml(Memb_list* ml, int type, NrnThread& nt) { int sz = corenrn.get_prop_param_size()[type]; int psz = corenrn.get_prop_dparam_size()[type]; @@ -379,6 +422,7 @@ int nrn_index_permute(int ix, int type, Memb_list* ml) { return i_sz * padded_cnt + p[i_cnt]; } } +#endif // CORENRN_BUILD #if CORENRN_DEBUG static void pr(const char* s, int* x, int n) { @@ -414,20 +458,39 @@ static bool nrn_index_sort_cmp(const std::pair& a, const std::pair nrn_index_sort(int* values, int n) { +#endif std::vector> vi(n); for (int i = 0; i < n; ++i) { vi[i].first = values[i]; vi[i].second = i; } std::sort(vi.begin(), vi.end(), nrn_index_sort_cmp); +#if CORENRN_BUILD int* sort_indices = new int[n]; +#else + std::vector sort_indices(n); +#endif for (int i = 0; i < n; ++i) { sort_indices[i] = vi[i].second; } return sort_indices; } +#if !CORENRN_BUILD +void sort_ml(Memb_list* ml) { + auto isrt = nrn_index_sort(ml->nodeindices, ml->nodecount); + forward_permute(ml->nodeindices, ml->nodecount, isrt); + forward_permute(ml->nodelist, ml->nodecount, isrt); + forward_permute(ml->prop, ml->nodecount, isrt); + forward_permute(ml->pdata, ml->nodecount, isrt); +} +#endif // !CORENRN_BUILD + +#if CORENRN_BUILD void permute_nodeindices(Memb_list* ml, int* p) { // nodeindices values are permuted according to p (that per se does // not affect vec). @@ -444,4 +507,6 @@ void permute_nodeindices(Memb_list* ml, int* p) { invert_permute(ml->_permute, ml->nodecount); permute_ptr(ml->nodeindices, ml->nodecount, ml->_permute); } +#endif // CORENRN_BUILD + } // namespace coreneuron diff --git a/src/coreneuron/permute/node_permute.h b/src/coreneuron/permute/node_permute.h index d453e656ab..541ebb73fd 100644 --- a/src/coreneuron/permute/node_permute.h +++ b/src/coreneuron/permute/node_permute.h @@ -8,14 +8,34 @@ #pragma once +#if CORENRN_BUILD #include "coreneuron/sim/multicore.hpp" +#else +#include "nrnoc/multicore.h" +#endif +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif // determine ml->_permute and permute the ml->nodeindices accordingly void permute_nodeindices(Memb_list* ml, int* permute); +#if CORENRN_BUILD // vec values >= 0 updated according to permutation void node_permute(int* vec, int n, int* permute); +#else // not CORENRN_BUILD +// sort ml fields in increasing node index order +void sort_ml(Memb_list* ml); + +/* + * Update indices vector so that the parent-child relation is kept valid + * after applying a permutation to the vector `vec`. + * This is done by updating vec values >= 0 according to the permutation. + */ +void update_parent_index(int* vec, int vec_size, const std::vector& permute); +#endif // not CORENRN_BUILD // moves values to new location but does not change those values void permute_ptr(int* vec, int n, int* permute); diff --git a/src/coreneuron/utils/lpt.cpp b/src/coreneuron/utils/lpt.cpp index 78c95b6294..775b634589 100644 --- a/src/coreneuron/utils/lpt.cpp +++ b/src/coreneuron/utils/lpt.cpp @@ -11,9 +11,14 @@ #include #include +#if CORENRN_BUILD #include "coreneuron/nrnconf.h" // for size_t -#include "coreneuron/utils/lpt.hpp" #include "coreneuron/utils/nrn_assert.h" +#else +#include "oc/nrnassrt.h" +#endif + +#include "coreneuron/utils/lpt.hpp" using P = std::pair; diff --git a/src/coreneuron/utils/memory.h b/src/coreneuron/utils/memory.h index 889049c121..e455c8aa87 100644 --- a/src/coreneuron/utils/memory.h +++ b/src/coreneuron/utils/memory.h @@ -13,8 +13,12 @@ #include #include +#if CORENRN_BUILD #include "coreneuron/utils/nrn_assert.h" #include "coreneuron/nrniv/nrniv_decl.h" +#else +#include "oc/nrnassrt.h" +#endif #if !defined(NRN_SOA_BYTE_ALIGN) // for layout 0, every range variable array must be aligned by at least 16 bytes (the size of the @@ -22,7 +26,11 @@ #define NRN_SOA_BYTE_ALIGN (8 * sizeof(double)) #endif +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif /** * @brief Check if GPU support is enabled. * @@ -183,7 +191,14 @@ inline void alloc_memory(void*& pointer, size_t num_bytes, size_t alignment) { size_t multiple = num_bytes / alignment; fill = alignment * (multiple + 1) - num_bytes; } +#ifndef _WIN32 nrn_assert((pointer = std::aligned_alloc(alignment, num_bytes + fill)) != nullptr); +#else // is _WIN32 + // Windows has _aligned_alloc, but that must be paired with + // _aligned_free + fprintf(stderr, "Windows has no std::aligned_alloc\n"); + nrn_assert((pointer = std::malloc(num_bytes)) != nullptr); +#endif // is _WIN32 } else { nrn_assert((pointer = std::malloc(num_bytes)) != nullptr); } @@ -200,18 +215,26 @@ inline void free_memory(void* pointer) { #endif +#if CORENRN_BUILD namespace coreneuron { +#else +namespace neuron { +#endif /** Independent function to compute the needed chunkding, the chunk argument is the number of doubles the chunk is chunkded upon. */ template inline int soa_padded_size(int cnt, int layout) { +#if CORENRN_BUILD if (layout == Layout::AoS) { return cnt; } else { return ((cnt + chunk - 1) / chunk) * chunk; } +#else + return ((cnt + chunk - 1) / chunk) * chunk; +#endif } /** Check for the pointer alignment. diff --git a/src/node_order_optim/README b/src/node_order_optim/README new file mode 100644 index 0000000000..5f20872dad --- /dev/null +++ b/src/node_order_optim/README @@ -0,0 +1,26 @@ +We wish to adopt into NEURON the CoreNEURON algorithms for node ordering. + + +interleave_order + node_order + tree_analysis + check + set_cellindex + set_groupindex + level_from_root + node_interleave_order if permute type 1 else group_order2 + check + quality + admin1 if permute type 1 else admin2 + return the permutation new int[nnode] + if thread 0 + print_quality1 if permute type 1 else print_quality2 + warp_balance + return order + +In CoreNEURON, phase2.cpp + nt._permute = interleave_order + apply the permutation to nodes, mechanisms, point processes + + +std::vector perm = interleave_order(int ith, int ncell, int nnode, int* parent); diff --git a/src/node_order_optim/node_order_optim.h b/src/node_order_optim/node_order_optim.h new file mode 100644 index 0000000000..f8519b9229 --- /dev/null +++ b/src/node_order_optim/node_order_optim.h @@ -0,0 +1,27 @@ +#pragma once + +namespace neuron { + +extern int interleave_permute_type; + +/// @brief Select node ordering for optimum gaussian elimination +/// @param type +/// 0 cell together (Section construction order) +/// 1 Interleave, identical cells warp adjacent +/// 2 Depth order, optimize adjacent nodes to have adjacent parents. +void nrn_optimize_node_order(int type); + +/// @brief Compute and carry out the permutation for interleave_permute_type +void nrn_permute_node_order(); + +/** + * + * \brief Solve the Hines matrices based on the interleave_permute_type (1 or 2). + * + * For interleave_permute_type == 1 : Naive interleaving -> Each execution thread deals with one + * Hines matrix (cell) For interleave_permute_type == 2 : Advanced interleaving -> Each Hines matrix + * is solved by multiple execution threads (with coalesced memory access as well) + */ +extern void solve_interleaved(int ith); + +} // namespace neuron diff --git a/src/node_order_optim/permute_utils.hpp b/src/node_order_optim/permute_utils.hpp new file mode 100644 index 0000000000..68c2fe6af6 --- /dev/null +++ b/src/node_order_optim/permute_utils.hpp @@ -0,0 +1,37 @@ +#include +#include + +template +void forward_permute(std::vector& data, const std::vector& perm) { + // Move data[perm[i]] to data[i] + std::vector new_data; + new_data.reserve(data.size()); + std::transform(perm.begin(), perm.end(), std::back_inserter(new_data), [&data](int ind) { + return data[ind]; + }); + data = std::move(new_data); +} + +template +void forward_permute(T*& data, int data_size, const std::vector& perm) { + // Move data[perm[i]] to data[i] + auto new_data = new T[data_size]; + for (auto i = 0; i < perm.size(); ++i) { + new_data[i] = data[perm[i]]; + } + // cannot std::swap because data may have been allocated by malloc + // std::swap(data, new_data); + for (auto i = 0; i < perm.size(); ++i) { + data[i] = new_data[i]; + } + delete[] new_data; +} + +template +std::vector inverse_permute_vector(const std::vector& p) { + std::vector pinv(p.size()); + for (int i = 0; i < p.size(); ++i) { + pinv[p[i]] = i; + } + return pinv; +} diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index 48f1c16531..ad2b41396d 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -149,6 +149,7 @@ set(NRN_OC_GENERATED_SOURCES # ============================================================================= set(NRN_NRNIV_LIB_SRC_FILES ${NRN_IVOC_SRC_FILES} + ${NRN_NODEORDEROPTIM_SRC_FILES} ${NRN_NRNCVODE_SRC_FILES} ${NRN_NRNIV_SRC_FILES} ${NRN_NRNOC_SRC_FILES} diff --git a/src/nrnoc/fadvance.cpp b/src/nrnoc/fadvance.cpp index 11dc9b89df..a8a06f314e 100644 --- a/src/nrnoc/fadvance.cpp +++ b/src/nrnoc/fadvance.cpp @@ -8,6 +8,7 @@ #include "nrn_ansi.h" #include "nrniv_mf.h" #include "multisplit.h" +#include "node_order_optim/node_order_optim.h" #define nrnoc_fadvance_c #include "utils/profile/profiler_interface.h" #include "nonvintblock.h" @@ -474,7 +475,11 @@ static void nrn_fixed_step_thread(neuron::model_sorted_token const& cache_token, setup_tree_matrix(cache_token, nt); { nrn::Instrumentor::phase p("matrix-solver"); - nrn_solve(nth); + if (neuron::interleave_permute_type) { + neuron::solve_interleaved(nt.id); + } else { + nrn_solve(nth); + } } { nrn::Instrumentor::phase p("second-order-cur"); diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index 16642afaa7..86e1e6992d 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -9,6 +9,7 @@ #include "neuron/cache/mechanism_range.hpp" #include "neuron/cache/model_data.hpp" #include "neuron/container/soa_container.hpp" +#include "node_order_optim/node_order_optim.h" #include "nonvintblock.h" #include "nrndae_c.h" #include "nrniv_mf.h" @@ -1757,12 +1758,43 @@ void v_setup_vectors(void) { } } neuron::model().node_data().mark_as_unsorted(); + // The assumption here is that one can arbitrarily permute the + // NrnThread node order (within the constraint that + // parent index < node index). A NrnThread node order permutation + // involves modifying NrnThread fields: _v_node, _v_parent, v_parent_index, + // and Node.v_node_index. + // Additionally, there appears to be a Memb_list node_indices ordering + // presumption embodied in nrn_sort_mech_data. I.e. Preexisting Memb_list node + // order is the order that results by iterating over Nrnthread nodes + // asserted by ml->nodelist[nt_mech_count] == nd. + // We this by monotonically ordering the Memb_list with + // sort_ml(Memb_list*) but there is a question whether the sort preserves + // the order when there are many POINT_PROCESS instances in the same node. + neuron::nrn_permute_node_order(); + v_structure_change = 0; nrn_update_ps2nt(); ++structure_change_cnt; long_difus_solve(nrn_ensure_model_data_are_sorted(), 3, *nrn_threads); // !!! nrn_nonvint_block_setup(); diam_changed = 1; + +#if 0 + for (int tid = 0; tid < nrn_nthread; ++tid) { + printf("nrnthread %d node info\n", tid); + auto& nt = nrn_threads[tid]; + for (int i = 0; i < nt.end; ++i) { + printf( + " _v_node[%2d]->v_node_index=%2d" + " _v_parent[%2d]->v_node_index=%2d v=%g\n", + i, + nt._v_node[i]->v_node_index, + i, + nt._v_parent[i] ? nt._v_parent[i]->v_node_index : -1, + (*nt._v_node[i]).v()); + } + } +#endif // 0 } diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index e71cb56900..7462d149b3 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -13,6 +13,7 @@ #include "multicore.h" #include "nrnpy.h" #include "utils/profile/profiler_interface.h" +#include "node_order_optim/node_order_optim.h" #include #include @@ -956,6 +957,14 @@ static double thread_how_many_proc(void*) { return double(i); } +static double optimize_node_order(void*) { + hoc_return_type_code = 1; // integer + if (ifarg(1)) { + neuron::nrn_optimize_node_order(int(chkarg(1, 0, 2))); + } + return double(neuron::interleave_permute_type); +} + static double sec_in_thread(void*) { hoc_return_type_code = 2; // boolean Section* sec = chk_access(); @@ -1112,6 +1121,7 @@ static Member_func members[] = {{"submit", submit}, {"thread_stat", thread_stat}, {"thread_busywait", thread_busywait}, {"thread_how_many_proc", thread_how_many_proc}, + {"optimize_node_order", optimize_node_order}, {"sec_in_thread", sec_in_thread}, {"thread_ctime", thread_ctime}, {"dt", thread_dt}, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d696d3b76a..199de0a117 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,6 +22,7 @@ add_executable( unit_tests/container/generic_data_handle.cpp unit_tests/container/mechanism.cpp unit_tests/container/node.cpp + unit_tests/node_order_optim/permutations.cpp unit_tests/utils/enumerate.cpp unit_tests/oc/hoc_interpreter.cpp cover/unit_tests/cover.cpp) diff --git a/test/external/CMakeLists.txt b/test/external/CMakeLists.txt index c4dfafe589..5dcf1a4bce 100644 --- a/test/external/CMakeLists.txt +++ b/test/external/CMakeLists.txt @@ -7,7 +7,7 @@ include(FetchContent) FetchContent_Declare( ringtest GIT_REPOSITORY https://github.com/neuronsimulator/ringtest - GIT_TAG d40caf64ac24c6ddcf2c082f4b0b7f7ca50657c9 + GIT_TAG 4ede4751c68f72a9884c6af4f94f65ff638054a8 SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/ringtest) FetchContent_Declare( diff --git a/test/external/ringtest/CMakeLists.txt b/test/external/ringtest/CMakeLists.txt index 22edacc360..a6383de6db 100644 --- a/test/external/ringtest/CMakeLists.txt +++ b/test/external/ringtest/CMakeLists.txt @@ -46,6 +46,20 @@ nrn_add_test( ENVIRONMENT NEURON_INIT_MPI=1 COMMAND ${ringtest_python} -tstop 100) +# creep into this file to add a nrn only test for ParallelContext.optimize_node_order(i) +nrn_add_test_group( + NAME external_ringtest_nrn + SUBMODULE tests/ringtest # git submodule where the relevant tests are defined + ENVIRONMENT OMP_NUM_THREADS=1 + MODFILE_PATTERNS "mod/*.mod" + SCRIPT_PATTERNS "*.py" "*.hoc") + +nrn_add_test( + GROUP external_ringtest_nrn + NAME optim_node_order + REQUIRES python + COMMAND nrniv -python test_optimize_node_order.py -tstop 50 -rparm -npt 1) + foreach(processor cpu gpu) if("${processor}" STREQUAL "gpu") set(gpu_arg -gpu) diff --git a/test/hoctests/tests/test_nrniv-launch.py b/test/hoctests/tests/test_nrniv-launch.py index c9407da81d..43682dee88 100644 --- a/test/hoctests/tests/test_nrniv-launch.py +++ b/test/hoctests/tests/test_nrniv-launch.py @@ -40,6 +40,7 @@ def nrniv(args, input): print "a = ", a print "square(a)=", square(a) quit() + """, ) diff --git a/test/hoctests/tests/test_optim_node_order.json b/test/hoctests/tests/test_optim_node_order.json new file mode 100644 index 0000000000..afee3567b3 --- /dev/null +++ b/test/hoctests/tests/test_optim_node_order.json @@ -0,0 +1,86 @@ +{ + "node order 0 nthread 1": [ + 10.0, + 20.0, + 30.0, + 11.0, + 12.0, + 21.0, + 22.0, + 23.0, + 31.0, + 32.0, + 33.0, + 34.0 + ], + "node order 1 nthread 1": [ + 10.0, + 20.0, + 30.0, + 11.0, + 21.0, + 31.0, + 12.0, + 22.0, + 32.0, + 23.0, + 33.0, + 34.0 + ], + "node order 2 nthread 1": [ + 10.0, + 20.0, + 30.0, + 11.0, + 21.0, + 31.0, + 22.0, + 32.0, + 33.0, + 12.0, + 23.0, + 34.0 + ], + "node order 0 nthread 2": [ + 10.0, + 20.0, + 11.0, + 12.0, + 21.0, + 22.0, + 23.0, + 30.0, + 31.0, + 32.0, + 33.0, + 34.0 + ], + "node order 1 nthread 2": [ + 10.0, + 20.0, + 11.0, + 21.0, + 12.0, + 22.0, + 23.0, + 30.0, + 31.0, + 32.0, + 33.0, + 34.0 + ], + "node order 2 nthread 2": [ + 10.0, + 20.0, + 11.0, + 21.0, + 22.0, + 12.0, + 23.0, + 30.0, + 31.0, + 32.0, + 33.0, + 34.0 + ] +} diff --git a/test/hoctests/tests/test_optim_node_order.py b/test/hoctests/tests/test_optim_node_order.py new file mode 100644 index 0000000000..7a5f1c979b --- /dev/null +++ b/test/hoctests/tests/test_optim_node_order.py @@ -0,0 +1,95 @@ +from neuron import h +from neuron.tests.utils.checkresult import Chk +import os + +# Create a helper for managing reference results +dir_path = os.path.dirname(os.path.realpath(__file__)) +chk = Chk(os.path.join(dir_path, "test_optim_node_order.json")) + +pc = h.ParallelContext() + +# Default Node order for simulation given a particular construction order +# is the order of section creation. + + +class Cell: + def __init__(self, id): + self.id = id + d = self.den = h.Section(name="d", cell=self) + d.nseg = id + for i, seg in enumerate(d.allseg()): + seg.v = i + 10 * id + + pc.set_gid2node(id, pc.id()) + pc.cell(id, h.NetCon(d(1)._ref_v, None, sec=d)) + syns = self.syns = [h.ExpSyn(d(0)) for i in range(3)] + for i, syn in enumerate(syns): + syn.tau = i + 10 * id + + def __str__(self): + return "Cell_%d" % self.id + + +cells = [Cell(id) for id in range(1, 4)] + +pr = False + + +def printv(): + s = {} # associate root sections with thread id. + for i in range(pc.nthread()): + for sec in pc.get_partition(i): + s[sec] = i + if pr: + print(s) + ns = 0 + for sec in h.allsec(): + for seg in sec.allseg(): + if pr: + print( + seg, + seg.v, + seg.node_index(), + seg._ref_v, + str(s[sec] if sec in s else ""), + ) + ns += 1 + + names = [None for i in range(ns)] + for sec in h.allsec(): + for seg in sec.allseg(): + ix = int(str(seg._ref_v).split()[1][4:].split("/")[0]) + names[ix] = seg.v + for i, seg in enumerate(names): + if pr: + print(i, seg) + tag = "node order %d nthread %d" % (pc.optimize_node_order(), pc.nthread()) + chk(tag, names) + + +# printv() + +# Iteration order (sec,seg) is associated with construction order +# (provided nseg set after each section construction?) +# and the only difference in simulation order is that all root nodes are at the beginning. +# (provided there is only one thread) + + +def pvmes(i): + if pr: + print("node order %d nthread %d" % (i, pc.nthread())) + h.finitialize() + printv() + + +def p(): + for i in range(3): + pc.optimize_node_order(i) + pvmes(i) + + +p() +pc.nthread(2) +p() + +chk.save() diff --git a/test/unit_tests/node_order_optim/permutations.cpp b/test/unit_tests/node_order_optim/permutations.cpp new file mode 100644 index 0000000000..15cb63f6ea --- /dev/null +++ b/test/unit_tests/node_order_optim/permutations.cpp @@ -0,0 +1,30 @@ +#include "node_order_optim/permute_utils.hpp" + +#include + +#include + +TEST_CASE("Permutation algorithms", "[Neuron][node_order_optim][permute]") { + GIVEN("A vector of elements and a permutation vector") { + const std::vector values{49, 32, 17, 29}; + const std::vector forward_permutation{3, 2, 0, 1}; + const std::vector inverse_permutation{2, 3, 1, 0}; + THEN("forward_permute is done correctly") { + std::vector forward_permutted_values{29, 17, 49, 32}; + auto values_copy{values}; + forward_permute(values_copy, forward_permutation); + REQUIRE(values_copy == forward_permutted_values); + } + THEN("Inversion of the permute vector is done correctly") { + REQUIRE(inverse_permute_vector(forward_permutation) == inverse_permutation); + /// Make sure that pinv[p[i]] = i = p[pinv[i]] + const std::vector index{0, 1, 2, 3}; + auto permutation_copy{forward_permutation}; + forward_permute(permutation_copy, inverse_permutation); + REQUIRE(permutation_copy == index); + auto inverse_permutation_copy{inverse_permutation}; + forward_permute(inverse_permutation_copy, forward_permutation); + REQUIRE(inverse_permutation_copy == index); + } + } +} From d96d2c2654996dbebe5f76faa21213549b7d230c Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Thu, 18 Apr 2024 17:55:59 +0200 Subject: [PATCH 39/62] CoreNEURON dependency issues. (#2839) --- CMakeLists.txt | 4 +++- bin/nrnivmodl_core_makefile.in | 2 +- bin/nrnivmodl_makefile_cmake.in | 2 +- external/coding-conventions | 2 +- external/nmodl | 2 +- src/coreneuron/CMakeLists.txt | 15 +++++++++------ src/nrniv/CMakeLists.txt | 22 ++++++++++++++++------ 7 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5372ac5d3..ecdec04d5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -733,7 +733,7 @@ add_custom_target( # ============================================================================= # ~~~ # Update hh.mod for CoreNEURON compatibility -# - Replace GLOBAL variable by RANHE +# - Replace GLOBAL variable by RANGE # - Comment out TABLE # ~~~ # ============================================================================= @@ -830,10 +830,12 @@ if(NRN_ENABLE_TESTS) set(neurondemo_files "${neurondemo_prefix}/special" "${neurondemo_prefix}/${CMAKE_SHARED_LIBRARY_PREFIX}nrnmech${CMAKE_SHARED_LIBRARY_SUFFIX}") + add_custom_command( OUTPUT ${neurondemo_files} COMMAND ${CMAKE_COMMAND} -E env ${NRN_RUN_FROM_BUILD_DIR_ENV} ${NRN_SANITIZER_ENABLE_ENVIRONMENT} "${PROJECT_BINARY_DIR}/bin/nrnivmodl" + DEPENDS nrnivmodl_dependency WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/share/nrn/demo/release VERBATIM) diff --git a/bin/nrnivmodl_core_makefile.in b/bin/nrnivmodl_core_makefile.in index 90acecb724..089cd6834f 100644 --- a/bin/nrnivmodl_core_makefile.in +++ b/bin/nrnivmodl_core_makefile.in @@ -145,7 +145,7 @@ endif # main target to build binary -$(SPECIAL_EXE): $(corenrnmech_lib_target) +$(SPECIAL_EXE): $(corenrnmech_lib_target) $(CORENRN_SHARE_CORENRN_DIR)/coreneuron.cpp @printf " => $(C_GREEN)Binary$(C_RESET) creating $(SPECIAL_EXE)\n" $(CXX_LINK_EXE_CMD) -o $(SPECIAL_EXE) $(CORENRN_SHARE_CORENRN_DIR)/coreneuron.cpp \ -I$(CORENRN_INC_DIR) $(INCFLAGS) \ diff --git a/bin/nrnivmodl_makefile_cmake.in b/bin/nrnivmodl_makefile_cmake.in index 71eade96ae..49164a7656 100644 --- a/bin/nrnivmodl_makefile_cmake.in +++ b/bin/nrnivmodl_makefile_cmake.in @@ -121,7 +121,7 @@ C_GREEN := \033[32m # Take the main and link with nrnmech. # RPATH is set for DESTDIR_RPATH and coreneuron lib -special: $(mech_lib) +special: $(mech_lib) $(datadir)/nrnmain.cpp @printf " => $(C_GREEN)LINKING$(C_RESET) executable \"${PWD}/$(special)\" LDFLAGS are: $(LDFLAGS)\n" $(CXX_LINK_EXE) -I $(incdir) -I $(incdir)/nrncvode -DAUTO_DLOPEN_NRNMECH=0 $(datadir)/nrnmain.cpp -o $(special) \ -L$(OBJS_DIR) -l$(mech_libname) $(NRNLIB_FLAGS) -l$(mech_libname) $(extra_lib_link) -Wl,-rpath,'$(DESTDIR_RPATH)' -Wl,-rpath,$(libdir) $(LDFLAGS) $(EXTRA_LDFLAGS) diff --git a/external/coding-conventions b/external/coding-conventions index 80a2c90134..3d157f9c8e 160000 --- a/external/coding-conventions +++ b/external/coding-conventions @@ -1 +1 @@ -Subproject commit 80a2c9013463b89b5c426e18403e9a2f87c59a00 +Subproject commit 3d157f9c8ea94d196a825aaa7f523265e360dc4b diff --git a/external/nmodl b/external/nmodl index 8f7eb99fd3..df2343ee54 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit 8f7eb99fd36ab886eac5c1ab050272fd2c46fa04 +Subproject commit df2343ee54b703d20979ff6f6d4f1a518b3597ac diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index d0a8c42e84..737fe30485 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -382,8 +382,14 @@ cpp_cc_build_time_copy( INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${ENGINEMECH_CODE_FILE}" OUTPUT "${CMAKE_BINARY_DIR}/share/coreneuron/enginemech.cpp" NO_TARGET) -set(nrnivmodl_core_dependencies "${CMAKE_BINARY_DIR}/share/coreneuron/mod_func.c.pl" - "${CMAKE_BINARY_DIR}/share/coreneuron/enginemech.cpp") +cpp_cc_build_time_copy( + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/apps/coreneuron.cpp" + OUTPUT "${CMAKE_BINARY_DIR}/share/coreneuron/coreneuron.cpp" + NO_TARGET) +set(nrnivmodl_core_dependencies + "${CMAKE_BINARY_DIR}/share/coreneuron/mod_func.c.pl" + "${CMAKE_BINARY_DIR}/share/coreneuron/enginemech.cpp" + "${CMAKE_BINARY_DIR}/share/coreneuron/coreneuron.cpp") # Set up build rules that copy builtin mod files from src/coreneuron/mechanism/mech/modfile/*.mod to # {build_dir}/share/modfile/ file(GLOB builtin_modfiles "${PROJECT_SOURCE_DIR}/src/coreneuron/mechanism/mech/modfile/*.mod") @@ -472,6 +478,7 @@ endif() # Hines solver. This cannot be included in coreneuron-core because of this issue: # https://forums.developer.nvidia.com/t/cannot-dynamically-load-a-shared-library-containing-both-openacc-and-cuda-code/210972 add_library(coreneuron-core STATIC ${CORENEURON_CODE_FILES} ${CORENRN_MPI_OBJ}) +add_dependencies(coreneuron-core coreneuron-copy-nrnivmodl-core-dependencies) if(CORENRN_ENABLE_GPU) set(coreneuron_cuda_target coreneuron-cuda) add_library(coreneuron-cuda ${COMPILE_LIBRARY_TYPE} ${CORENEURON_CUDA_FILES}) @@ -650,10 +657,6 @@ endforeach() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/utils/profile/profiler_interface.h ${CMAKE_BINARY_DIR}/include/coreneuron/nrniv/profiler_interface.h COPYONLY) -# main program required for building special-core -cpp_cc_build_time_copy(INPUT ${CMAKE_CURRENT_SOURCE_DIR}/apps/coreneuron.cpp - OUTPUT ${CMAKE_BINARY_DIR}/share/coreneuron/coreneuron.cpp) - # Extract the various compiler option strings to use inside nrnivmodl-core. Sets the global property # CORENRN_LIB_LINK_FLAGS, which contains the arguments that must be added to the link line for # `special` to link against `libcorenrnmech_internal.{a,so}` diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index ad2b41396d..c9331147c3 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -582,14 +582,24 @@ endif() # ============================================================================= # For testneuron CTest -cpp_cc_build_time_copy(INPUT ${PROJECT_SOURCE_DIR}/src/ivoc/nrnmain.cpp - OUTPUT ${CMAKE_BINARY_DIR}/share/nrn/nrnmain.cpp) +cpp_cc_build_time_copy( + INPUT ${PROJECT_SOURCE_DIR}/src/ivoc/nrnmain.cpp OUTPUT ${CMAKE_BINARY_DIR}/share/nrn/nrnmain.cpp + TARGET nrnivmodl_nrnmain_cpp) + cpp_cc_build_time_copy(INPUT ${PROJECT_BINARY_DIR}/src/oc/nrnmpiuse.h - OUTPUT ${CMAKE_BINARY_DIR}/include/nrnmpiuse.h) -cpp_cc_build_time_copy(INPUT ${PROJECT_BINARY_DIR}/src/nrncvode/nrnneosm.h - OUTPUT ${CMAKE_BINARY_DIR}/include/nrncvode/nrnneosm.h) + OUTPUT ${CMAKE_BINARY_DIR}/include/nrnmpiuse.h TARGET nrnivmodl_nrnmpiuse_h) + +cpp_cc_build_time_copy( + INPUT ${PROJECT_BINARY_DIR}/src/nrncvode/nrnneosm.h + OUTPUT ${CMAKE_BINARY_DIR}/include/nrncvode/nrnneosm.h TARGET nrnivmodl_nrnneosm_h) + cpp_cc_build_time_copy(INPUT ${PROJECT_BINARY_DIR}/nrnconf.h - OUTPUT ${CMAKE_BINARY_DIR}/include/nrnconf.h) + OUTPUT ${CMAKE_BINARY_DIR}/include/nrnconf.h TARGET nrnivmodl_nrnconf_h) + +add_custom_target( + nrnivmodl_dependency ALL + DEPENDS ${CMAKE_BINARY_DIR}/share/nrn/nrnmain.cpp ${CMAKE_BINARY_DIR}/include/nrnmpiuse.h + ${CMAKE_BINARY_DIR}/include/nrncvode/nrnneosm.h ${CMAKE_BINARY_DIR}/include/nrnconf.h) # For the installation install(FILES ${PROJECT_SOURCE_DIR}/src/ivoc/nrnmain.cpp DESTINATION share/nrn) From d5dd1ce7053a3207aef1d3a96d98c2967012d864 Mon Sep 17 00:00:00 2001 From: Jorge Blanco Alonso <41900536+jorblancoa@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:43:51 +0200 Subject: [PATCH 40/62] Remove contribution of SEClamp and IClamp to lfp (#2841) * Fix read_mapping_info issue: use read_vector for lfp_factors --- src/coreneuron/io/nrn_filehandler.hpp | 4 +--- src/coreneuron/io/reports/report_handler.cpp | 21 -------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/coreneuron/io/nrn_filehandler.hpp b/src/coreneuron/io/nrn_filehandler.hpp index 3241fd3506..672af88404 100644 --- a/src/coreneuron/io/nrn_filehandler.hpp +++ b/src/coreneuron/io/nrn_filehandler.hpp @@ -132,9 +132,7 @@ class FileHandler { std::vector lfp_factors; if (total_lfp_factors > 0) { - // ASan reports container overflow on read_array with vec.reserve, resize does work - lfp_factors.resize(nseg); - read_array(&lfp_factors[0], total_lfp_factors); + lfp_factors = read_vector(total_lfp_factors); } int factor_offset = 0; diff --git a/src/coreneuron/io/reports/report_handler.cpp b/src/coreneuron/io/reports/report_handler.cpp index 0fd48d7a0a..de1cfd64f3 100644 --- a/src/coreneuron/io/reports/report_handler.cpp +++ b/src/coreneuron/io/reports/report_handler.cpp @@ -354,24 +354,6 @@ VarsToReport ReportHandler::get_synapse_vars_to_report( return vars_to_report; } -void add_clamp_current(const char* clamp, - const NrnThread& nt, - std::unordered_map>>& currents, - int gid, - const std::vector& nodes_to_gids) { - auto mech_id = nrn_get_mechtype(clamp); - Memb_list* ml = nt._ml_list[mech_id]; - if (ml) { - for (int i = 0; i < ml->nodecount; i++) { - auto segment_id = ml->nodeindices[i]; - if ((nodes_to_gids[segment_id] == gid)) { - double* var_value = get_var_location_from_var_name(mech_id, "i", ml, i); - currents[segment_id].push_back(std::make_pair(var_value, -1)); - } - } - } -} - VarsToReport ReportHandler::get_lfp_vars_to_report(const NrnThread& nt, const std::vector& gids_to_report, ReportConfiguration& report, @@ -387,9 +369,6 @@ VarsToReport ReportHandler::get_lfp_vars_to_report(const NrnThread& nt, VarsToReport vars_to_report; off_t offset_lfp = 0; for (const auto& gid: gids_to_report) { - // IClamp & SEClamp are needed for the LFP calculation - add_clamp_current("IClamp", nt, summation_report.currents_, gid, nodes_to_gids); - add_clamp_current("SEClamp", nt, summation_report.currents_, gid, nodes_to_gids); const auto& cell_mapping = mapinfo->get_cell_mapping(gid); if (cell_mapping == nullptr) { std::cerr << "[LFP] Error : Compartment mapping information is missing for gid " << gid From 7803ccedee4867ed30969056e6d6e74d9fe28f62 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 19 Apr 2024 15:05:50 +0200 Subject: [PATCH 41/62] Fix CoreNEURON bug with array variables. (#2779) * Test to expose bug in array variables. This test exposes a bug in how data is copied between NEURON and CoreNEURON. It must include (at least) one MOD file with array range variables. It must check that the copy of these array range variables received by CoreNEURON is correct. The suspected bug is that an array range variable with M elements is sometimes 1 and sometimes M "floating point variables"; and somehow this is done inconsistently. * Store number of doubles in `nrn_prop_param_size_`. Change `register_data_fields` to compute the number of doubles required by a mechanism, and store that number, as opposed to the number of variables/fields in the SoA, in the global `nrn_prop_param_size_`. * Transfer `array_dims` to CoreNEURON. Either via `bbcore_mech.dat` or directly via the stringstream. * Implement CNRN->NRN SoAoS copy. * Fix transpose during NRN->CoreNEURON (file_mode). * Fix transpose during NRN->CoreNEURON (in-memory). * Implement `legacy2soaos_index` and `soaos2cnrn_index`. The two function convert legacy indices to CoreNEURON indices, i.e. the index of the value inside the CoreNEURON datastructures. --------- Co-authored-by: Pramod Kumbhar Co-authored-by: Michael Hines --- external/nmodl | 2 +- src/coreneuron/apps/main1.cpp | 2 +- src/coreneuron/coreneuron.hpp | 5 + src/coreneuron/io/core2nrn_data_return.cpp | 96 ++++++++----- src/coreneuron/io/mem_layout_util.cpp | 56 +++++--- src/coreneuron/io/mem_layout_util.hpp | 41 +++++- src/coreneuron/io/mk_mech.cpp | 11 +- src/coreneuron/io/nrn_setup.cpp | 20 +-- src/coreneuron/io/phase2.cpp | 79 +++++++---- src/coreneuron/mechanism/register_mech.cpp | 1 + src/coreneuron/network/partrans_setup.cpp | 6 +- src/coreneuron/nrniv/nrniv_decl.h | 4 +- src/coreneuron/permute/node_permute.cpp | 20 --- src/coreneuron/permute/node_permute.h | 1 - src/coreneuron/utils/nrnoc_aux.cpp | 2 +- src/nmodl/nocpout.cpp | 8 +- .../callbacks/nrncore_callbacks.cpp | 20 ++- .../callbacks/nrncore_callbacks.h | 2 +- src/nrniv/nrncore_write/io/nrncore_io.cpp | 2 +- .../nrncore_write/utils/nrncore_utils.cpp | 7 +- src/nrniv/partrans.cpp | 2 +- src/nrnoc/extcelln.cpp | 3 +- src/nrnoc/init.cpp | 15 +- src/nrnoc/memblist.cpp | 26 ++++ src/nrnoc/nrnoc_ml.h | 27 ++++ test/CMakeLists.txt | 19 +++ test/coreneuron/mod files/green.mod | 25 ++++ test/coreneuron/mod files/red.mod | 25 ++++ .../test_array_variables_transfer.py | 134 ++++++++++++++++++ 29 files changed, 522 insertions(+), 139 deletions(-) create mode 100644 test/coreneuron/mod files/green.mod create mode 100644 test/coreneuron/mod files/red.mod create mode 100644 test/coreneuron/test_array_variables_transfer.py diff --git a/external/nmodl b/external/nmodl index df2343ee54..f6821cea1a 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit df2343ee54b703d20979ff6f6d4f1a518b3597ac +Subproject commit f6821cea1af81eb3061fbfff6552f0c776ef7626 diff --git a/src/coreneuron/apps/main1.cpp b/src/coreneuron/apps/main1.cpp index c5d5b3d2db..8d2e0ca688 100644 --- a/src/coreneuron/apps/main1.cpp +++ b/src/coreneuron/apps/main1.cpp @@ -139,7 +139,7 @@ void get_nrn_trajectory_requests(int bsize) { tr->varrays = varrays; tr->scatter = pvars; for (int i = 0; i < n_trajec; ++i) { - tr->gather[i] = stdindex2ptr(types[i], indices[i], nt); + tr->gather[i] = legacy_index2pointer(types[i], indices[i], nt); } delete[] types; delete[] indices; diff --git a/src/coreneuron/coreneuron.hpp b/src/coreneuron/coreneuron.hpp index bf06c0de73..7031aeb0c4 100644 --- a/src/coreneuron/coreneuron.hpp +++ b/src/coreneuron/coreneuron.hpp @@ -90,6 +90,7 @@ class CoreNeuron { * Internal lookup tables. Number of float and int variables in each mechanism and memory layout * future --> mech class */ + std::vector> nrn_array_dims; std::vector nrn_prop_param_size; std::vector nrn_prop_dparam_size; std::vector nrn_mech_data_layout; /* 1 AoS (default), 0 SoA */ @@ -159,6 +160,10 @@ class CoreNeuron { return bamech; } + auto& get_array_dims() { + return nrn_array_dims; + } + auto& get_prop_param_size() { return nrn_prop_param_size; } diff --git a/src/coreneuron/io/core2nrn_data_return.cpp b/src/coreneuron/io/core2nrn_data_return.cpp index 3aa230911a..1ec5fc5201 100644 --- a/src/coreneuron/io/core2nrn_data_return.cpp +++ b/src/coreneuron/io/core2nrn_data_return.cpp @@ -63,45 +63,66 @@ static void inverse_permute_copy(size_t n, double* permuted_src, double* dest, i } } -/** @brief SoA permuted mechanism data copied to unpermuted AoS data. - * dest is an array of n pointers to the beginning of each sz length array. - * src is a contiguous array of sz segments of size stride. The stride - * may be slightly greater than n for purposes of alignment. - * Each of the sz segments of src are permuted. - */ -static void soa2aos_inverse_permute_copy(size_t n, - int sz, - int stride, - double* src, - std::vector& dest, - int* permute) { - // src is soa and permuted. dest is n pointers to sz doubles (aos). - for (size_t instance = 0; instance < n; ++instance) { - double* s = src + permute[instance]; - for (int i = 0; i < sz; ++i) { - dest[i][instance] = s[i * stride]; +// See `soaos_copy_cnrn2nrn` for documentation. +template +static void soaos_copy_cnrn2nrn_impl(size_t n, + int stride, + double const* const src, + std::vector& dest, + const std::vector& array_dims, + int* permute) { + // i : runs over instances: 0, ..., n. + // j : runs over variables: 0, ..., array_dims.size() =: n_vars. + // k : runs over array dimension: 0, ..., array_dims[i_var] =: K. + + int n_vars = array_dims.size(); + double const* src_var = src; + for (size_t j_var = 0; j_var < n_vars; ++j_var) { + size_t K = array_dims[j_var]; + + for (size_t i = 0; i < n; ++i) { + size_t i_src = needs_permute ? static_cast(permute[i]) : i; + for (size_t k = 0; k < K; ++k) { + dest[j_var][i * K + k] = src_var[i_src * K + k]; + } } + + src_var += stride * K; } } -/** @brief SoA unpermuted mechanism data copied to unpermuted AoS data. - * dest is an array of n pointers to the beginning of each sz length array. - * src is a contiguous array of sz segments of size stride. The stride - * may be slightly greater than n for purposes of alignment. - * Each of the sz segments of src have the same order as the n pointers - * of dest. +/** @brief SoAoS unpermuted mechanism data copied to unpermuted SoAoS data. + * + * This function copies the CoreNEURON SoAoS format into the NEURON format. There + * are two differences: + * 1. NRN allocates a separate array for each variable, while CoreNEURON + * allocates a single large chunk of memory. + * 2. CoreNEURON pads the instance number. + * + * For ARRAY variables both NRN and CoreNRN store consecutive elements of the + * array consecutively in memory. + * + * Let `K` be the number of variables, counting array variables as one + * variable. Then `dest` is an array of `K` pointers, one for each variable of + * the mechanism. The pointer `dest[i]` is an array of size `n*array_dims[i]` + * and the array element `k` for instance `i` is stored at `dest[i*n + k]`. + * + * The pointer `src` points to `stride*sum(array_dims)` doubles. + * + * If `permute != nullptr`, then then the instance is permuted, i.e. the + * instance index is `permute[i]` in `src` (and `i` in `dest`). If `permute == + * nullptr` no permutation is performed. */ -static void soa2aos_unpermuted_copy(size_t n, - int sz, - int stride, - double* src, - std::vector& dest) { - // src is soa and permuted. dest is n pointers to sz doubles (aos). - for (size_t instance = 0; instance < n; ++instance) { - double* s = src + instance; - for (int i = 0; i < sz; ++i) { - dest[i][instance] = s[i * stride]; - } +static void soaos_copy_cnrn2nrn(size_t n, + int stride, + double const* const src, + std::vector& dest, + const std::vector& array_dims, + int* permute) { + if (permute == nullptr) { + soaos_copy_cnrn2nrn_impl(n, stride, src, dest, array_dims, permute); + } else { + soaos_copy_cnrn2nrn_impl(n, stride, src, dest, array_dims, permute); } } @@ -327,13 +348,10 @@ void core2nrn_data_return() { double* cndat = ml->data; int layout = corenrn.get_mech_data_layout()[mtype]; int sz = corenrn.get_prop_param_size()[mtype]; + const std::vector& array_dims = corenrn.get_array_dims()[mtype]; if (layout == Layout::SoA) { int stride = ml->_nodecount_padded; - if (permute) { - soa2aos_inverse_permute_copy(n, sz, stride, cndat, mdata, permute); - } else { - soa2aos_unpermuted_copy(n, sz, stride, cndat, mdata); - } + soaos_copy_cnrn2nrn(n, stride, cndat, mdata, array_dims, permute); } else { /* AoS */ aos2aos_copy(n, sz, cndat, mdata); } diff --git a/src/coreneuron/io/mem_layout_util.cpp b/src/coreneuron/io/mem_layout_util.cpp index 3845303425..0551e049b3 100644 --- a/src/coreneuron/io/mem_layout_util.cpp +++ b/src/coreneuron/io/mem_layout_util.cpp @@ -8,6 +8,8 @@ #include "mem_layout_util.hpp" +#include + namespace coreneuron { /// calculate size after padding for specific memory layout @@ -42,23 +44,45 @@ int nrn_i_layout(int icnt, int cnt, int isz, int sz, int layout) { return 0; } -// file data is AoS. ie. -// organized as cnt array instances of mtype each of size sz. -// So input index i refers to i_instance*sz + i_item offset -// Return the corresponding SoA index -- taking into account the -// alignment requirements. Ie. i_instance + i_item*align_cnt. +std::array legacy2soaos_index(int legacy_index, const std::vector& array_dims) { + int variable_count = static_cast(array_dims.size()); + int row_width = std::accumulate(array_dims.begin(), array_dims.end(), 0); -int nrn_param_layout(int i, int mtype, Memb_list* ml) { - int layout = corenrn.get_mech_data_layout()[mtype]; - switch (layout) { - case Layout::AoS: - return i; - case Layout::SoA: - nrn_assert(layout == Layout::SoA); - int sz = corenrn.get_prop_param_size()[mtype]; - return nrn_i_layout(i / sz, ml->nodecount, i % sz, sz, layout); + int column_index = legacy_index % row_width; + + int instance_index = legacy_index / row_width; + int variable_index = 0; + int prefix_sum = 0; + for (size_t k = 0; k < variable_count - 1; ++k) { + if (column_index >= prefix_sum + array_dims[k]) { + prefix_sum += array_dims[k]; + variable_index = k + 1; + } else { + break; + } } - nrn_assert(false); - return 0; + int array_index = column_index - prefix_sum; + + return {instance_index, variable_index, array_index}; } + +int soaos2cnrn_index(const std::array& soaos_indices, + const std::vector& array_dims, + int padded_node_count, + int* permute) { + auto [i, j, k] = soaos_indices; + if (permute) { + i = permute[i]; + } + + int offset = 0; + for (int ij = 0; ij < j; ++ij) { + offset += padded_node_count * array_dims[ij]; + } + + int K = array_dims[j]; + return offset + i * K + k; +} + + } // namespace coreneuron diff --git a/src/coreneuron/io/mem_layout_util.hpp b/src/coreneuron/io/mem_layout_util.hpp index a6b2606011..501c451ec7 100644 --- a/src/coreneuron/io/mem_layout_util.hpp +++ b/src/coreneuron/io/mem_layout_util.hpp @@ -8,6 +8,8 @@ #pragma once +#include + #include "coreneuron/coreneuron.hpp" #include "coreneuron/nrniv/nrniv_decl.h" @@ -27,11 +29,38 @@ size_t nrn_soa_byte_align(size_t i); /// Depending of the layout some padding can be calculated int nrn_i_layout(int icnt, int cnt, int isz, int sz, int layout); -// file data is AoS. ie. -// organized as cnt array instances of mtype each of size sz. -// So input index i refers to i_instance*sz + i_item offset -// Return the corresponding SoA index -- taking into account the -// alignment requirements. Ie. i_instance + i_item*align_cnt. +/// \brief Split a legacy index into the three SoAoS indices. +/// +/// The legacy index is the AoS of the data, i.e. all values are arranged in a +/// table. Different variables and elements of those variables for array +/// variables occupy different columns, while different instances occupy +/// different rows. +/// +/// The legacy index is then simply the elements flat (one-dimensional) index +/// in that (unpadded) row-major table. +/// +/// Given this `legacy_index` and `array_dims`, i.e. the number of array +/// elements for each variable (1 for regular variables and >= 1 for array +/// variables), compute the triplet `(i, j, k)` where `i` is the index of the +/// instance, `j` of the variable, and `k` the of array element. +std::array legacy2soaos_index(int legacy_index, const std::vector& array_dims); + +/// \brief Compute the CoreNEURON index given an SoAoS index. +/// +/// The CoreNEURON index is the index in a flat array starting from a pointer +/// pointing to the beginning of the data of that mechanism. Note, that +/// CoreNEURON pads to the number of instances. +/// +/// If `permute` is not null, then the instance index `i` is permuted. Before +/// computing before computing the flat index. +/// +/// Consecutive array elements are always stored consecutively, next fastest +/// index is over instances, and the slowest index runs over variables. Note, +/// up to padding and permutation of the instances this is the same SoAoS order +/// as in NEURON. +int soaos2cnrn_index(const std::array& soaos_indices, + const std::vector& array_dims, + int padded_node_count, + int* permute); -int nrn_param_layout(int i, int mtype, Memb_list* ml); } // namespace coreneuron diff --git a/src/coreneuron/io/mk_mech.cpp b/src/coreneuron/io/mk_mech.cpp index 294ad28b0e..3750092a7b 100644 --- a/src/coreneuron/io/mk_mech.cpp +++ b/src/coreneuron/io/mk_mech.cpp @@ -92,9 +92,16 @@ static void mk_mech(std::istream& s) { /// Read all the mechanisms and their meta data for (int i = 2; i < n; ++i) { char mname[100]; - int type = 0, pnttype = 0, is_art = 0, is_ion = 0, dsize = 0, pdsize = 0; - nrn_assert(s >> mname >> type >> pnttype >> is_art >> is_ion >> dsize >> pdsize); + int type = 0, pnttype = 0, is_art = 0, is_ion = 0, dsize = 0, pdsize = 0, vsize = 0; + nrn_assert(s >> mname >> type >> pnttype >> is_art >> is_ion >> dsize >> pdsize >> vsize); nrn_assert(i == type); + + std::vector array_dims(vsize); + for (size_t i = 0; i < vsize; ++i) { + nrn_assert(s >> array_dims[i]); + } + corenrn.get_array_dims().at(type) = array_dims; + #ifdef DEBUG printf("%s %d %d %d %d %d %d\n", mname, type, pnttype, is_art, is_ion, dsize, pdsize); #endif diff --git a/src/coreneuron/io/nrn_setup.cpp b/src/coreneuron/io/nrn_setup.cpp index e2752454e7..285c19034a 100644 --- a/src/coreneuron/io/nrn_setup.cpp +++ b/src/coreneuron/io/nrn_setup.cpp @@ -496,7 +496,7 @@ void nrn_setup(const char* filesdat, // gap junctions // Gaps are done after phase2, in order to use layout and permutation - // information via calls to stdindex2ptr. + // information via calls to legacy_index2pointer. if (nrn_have_gaps) { nrn_partrans::transfer_thread_data_ = new nrn_partrans::TransferThreadData[nrn_nthread]; if (!corenrn_embedded) { @@ -634,7 +634,7 @@ void read_phasegap(NrnThread& nt, UserParams& userParams) { // mech_type enum or non-artificial cell mechanisms. // take into account alignment, layout, permutation // only voltage, i_membrane_ or mechanism data index allowed. (mtype 0 means time) -double* stdindex2ptr(int mtype, int index, NrnThread& nt) { +double* legacy_index2pointer(int mtype, int index, NrnThread& nt) { if (mtype == voltage) { // voltage int ix = index; // relative to _actual_v nrn_assert((ix >= 0) && (ix < nt.end)); @@ -652,15 +652,19 @@ double* stdindex2ptr(int mtype, int index, NrnThread& nt) { } else if (mtype > 0 && mtype < static_cast(corenrn.get_memb_funcs().size())) { // Memb_list* ml = nt._ml_list[mtype]; nrn_assert(ml); - int ix = nrn_param_layout(index, mtype, ml); - if (ml->_permute) { - ix = nrn_index_permute(ix, mtype, ml); - } - return ml->data + ix; + + const std::vector& array_dims = corenrn.get_array_dims()[mtype]; + int padded_node_count = nrn_soa_padded_size(ml->nodecount, Layout::SoA); + + auto soaos_index = legacy2soaos_index(index, array_dims); + auto cnrn_index = + soaos2cnrn_index(soaos_index, array_dims, padded_node_count, ml->_permute); + + return ml->data + cnrn_index; } else if (mtype == 0) { // time return &nt._t; } else { - printf("stdindex2ptr does not handle mtype=%d\n", mtype); + printf("legacy_index2pointer does not handle mtype=%d\n", mtype); nrn_assert(0); } return nullptr; diff --git a/src/coreneuron/io/phase2.cpp b/src/coreneuron/io/phase2.cpp index 0a62c2366c..19fb12e8a3 100644 --- a/src/coreneuron/io/phase2.cpp +++ b/src/coreneuron/io/phase2.cpp @@ -87,27 +87,41 @@ int (*nrn2core_get_dat2_vecplay_inst_)(int tid, namespace coreneuron { template -inline void mech_data_layout_transform(T* data, int cnt, int sz, int layout) { +void mech_data_layout_transform(T* data, int cnt, const std::vector& array_dims, int layout) { if (layout == Layout::AoS) { - return; - } - // layout is equal to Layout::SoA - int align_cnt = nrn_soa_padded_size(cnt, layout); - std::vector d(cnt * sz); - // copy matrix - for (int i = 0; i < cnt; ++i) { - for (int j = 0; j < sz; ++j) { - d[i * sz + j] = data[i * sz + j]; - } + throw std::runtime_error("AoS memory layout not implemented."); } - // transform memory layout - for (int i = 0; i < cnt; ++i) { - for (int j = 0; j < sz; ++j) { - data[i + j * align_cnt] = d[i * sz + j]; + + int n_vars = array_dims.size(); + int row_width = std::accumulate(array_dims.begin(), array_dims.end(), 0); + int padded_cnt = nrn_soa_padded_size(cnt, layout); + + std::vector tmp(padded_cnt * row_width); + std::copy(data, data + cnt * row_width, tmp.begin()); + + size_t offset_var = 0; + for (size_t i_var = 0; i_var < n_vars; ++i_var) { + size_t K = array_dims[i_var]; + + for (size_t i = 0; i < cnt; ++i) { + for (size_t k = 0; k < K; ++k) { + size_t i_dst = padded_cnt * offset_var + i * K + k; + size_t i_src = i * row_width + offset_var + k; + data[i_dst] = tmp[i_src]; + } } + + offset_var += K; } } +template +inline void mech_data_layout_transform(T* data, int cnt, int sz, int layout) { + std::vector array_dims(sz, 1); + mech_data_layout_transform(data, cnt, array_dims, layout); +} + + void Phase2::read_file(FileHandler& F, const NrnThread& nt) { n_real_cell = F.read_int(); n_output = F.read_int(); @@ -692,13 +706,17 @@ void Phase2::pdata_relocation(const NrnThread& nt, const std::vector& Memb_list* eml = nt._ml_list[etype]; int edata0 = eml->data - nt._data; int ecnt = eml->nodecount; + int ecnt_padded = nrn_soa_padded_size(ecnt, Layout::SoA); int esz = corenrn.get_prop_param_size()[etype]; + const std::vector& array_dims = corenrn.get_array_dims()[etype]; for (int iml = 0; iml < cnt; ++iml) { int* pd = pdata + nrn_i_layout(iml, cnt, i, szdp, layout); - int ix = *pd; // relative to the ion data - nrn_assert((ix >= 0) && (ix < ecnt * esz)); - /* Original pd order assumed ecnt groups of esz */ - *pd = edata0 + nrn_param_layout(ix, etype, eml); + int legacy_index = *pd; // relative to the ion data + nrn_assert((legacy_index >= 0) && (legacy_index < ecnt * esz)); + + auto soaos_index = legacy2soaos_index(legacy_index, array_dims); + *pd = edata0 + + soaos2cnrn_index(soaos_index, array_dims, ecnt_padded, nullptr); } } } @@ -722,10 +740,17 @@ void Phase2::pdata_relocation(const NrnThread& nt, const std::vector& } else { Memb_list* pml = nt._ml_list[ptype]; int pcnt = pml->nodecount; + int pcnt_padded = nrn_soa_padded_size(pcnt, Layout::SoA); int psz = corenrn.get_prop_param_size()[ptype]; + const std::vector& array_dims = + corenrn.get_array_dims()[ptype]; nrn_assert((ix >= 0) && (ix < pcnt * psz)); + int elem0 = pml->data - nt._data; - *pd = elem0 + nrn_param_layout(ix, ptype, pml); + auto soaos_index = legacy2soaos_index(ix, array_dims); + *pd = + elem0 + + soaos2cnrn_index(soaos_index, array_dims, pcnt_padded, nullptr); } } } @@ -920,10 +945,12 @@ void Phase2::set_vec_play(NrnThread& nt, NrnThreadChkpnt& ntc) { #endif Memb_list* ml = nt._ml_list[vecPlay.mtype]; - vecPlay.ix = nrn_param_layout(vecPlay.ix, vecPlay.mtype, ml); - if (ml->_permute) { - vecPlay.ix = nrn_index_permute(vecPlay.ix, vecPlay.mtype, ml); - } + const std::vector& array_dims = corenrn.get_array_dims()[vecPlay.mtype]; + + auto padded_nodecount = nrn_soa_padded_size(ml->nodecount, Layout::SoA); + auto soaos_index = legacy2soaos_index(vecPlay.ix, array_dims); + vecPlay.ix = soaos2cnrn_index(soaos_index, array_dims, padded_nodecount, ml->_permute); + nt._vecplay[i] = new VecPlayContinuous(ml->data + vecPlay.ix, std::move(vecPlay.yvec), std::move(vecPlay.tvec), @@ -1081,12 +1108,14 @@ void Phase2::populate(NrnThread& nt, const UserParams& userParams) { int n = ml->nodecount; int szp = nrn_prop_param_size_[type]; int szdp = nrn_prop_dparam_size_[type]; + + const std::vector& array_dims = corenrn.get_array_dims()[type]; int layout = corenrn.get_mech_data_layout()[type]; ml->nodeindices = (int*) ecalloc_align(ml->nodecount, sizeof(int)); std::copy(tmls[itml].nodeindices.begin(), tmls[itml].nodeindices.end(), ml->nodeindices); - mech_data_layout_transform(ml->data, n, szp, layout); + mech_data_layout_transform(ml->data, n, array_dims, layout); if (szdp) { ml->pdata = (int*) ecalloc_align(nrn_soa_padded_size(n, layout) * szdp, sizeof(int)); diff --git a/src/coreneuron/mechanism/register_mech.cpp b/src/coreneuron/mechanism/register_mech.cpp index 9853c1243a..260d420411 100644 --- a/src/coreneuron/mechanism/register_mech.cpp +++ b/src/coreneuron/mechanism/register_mech.cpp @@ -92,6 +92,7 @@ void alloc_mech(int memb_func_size_) { corenrn.get_watch_check().resize(memb_func_size_); corenrn.get_is_artificial().resize(memb_func_size_, false); corenrn.get_artcell_qindex().resize(memb_func_size_); + corenrn.get_array_dims().resize(memb_func_size_); corenrn.get_prop_param_size().resize(memb_func_size_); corenrn.get_prop_dparam_size().resize(memb_func_size_); corenrn.get_mech_data_layout().resize(memb_func_size_, 1); diff --git a/src/coreneuron/network/partrans_setup.cpp b/src/coreneuron/network/partrans_setup.cpp index 1c1a3f9010..6d474da619 100644 --- a/src/coreneuron/network/partrans_setup.cpp +++ b/src/coreneuron/network/partrans_setup.cpp @@ -160,7 +160,7 @@ void nrn_partrans::gap_mpi_setup(int ngroup) { // Note that src_index points into NrnThread.data, as it has already // been transformed using original src_type and src_index via - // stdindex2ptr. + // legacy_index2pointer. // For copying into outsrc_buf from src_gather. This is from // NrnThread._data, fixup to "from src_gather" below. ttd.gather2outsrc_indices.push_back(si.src_index[setup_info_index]); @@ -248,13 +248,13 @@ void nrn_partrans::gap_data_indices_setup(NrnThread* n) { // For copying into src_gather from NrnThread._data for (size_t i = 0; i < sti.src_sid.size(); ++i) { - double* d = stdindex2ptr(sti.src_type[i], sti.src_index[i], nt); + double* d = legacy_index2pointer(sti.src_type[i], sti.src_index[i], nt); sti.src_index[i] = int(d - nt._data); } // For copying into NrnThread._data from insrc_buf. for (size_t i = 0; i < sti.tar_sid.size(); ++i) { - double* d = stdindex2ptr(sti.tar_type[i], sti.tar_index[i], nt); + double* d = legacy_index2pointer(sti.tar_type[i], sti.tar_index[i], nt); // todo : this should be revisited once nt._data will be broken // into mechanism specific data sti.tar_index[i] = int(d - nt._data); diff --git a/src/coreneuron/nrniv/nrniv_decl.h b/src/coreneuron/nrniv/nrniv_decl.h index 00cdaef16d..32fe24dec7 100644 --- a/src/coreneuron/nrniv/nrniv_decl.h +++ b/src/coreneuron/nrniv/nrniv_decl.h @@ -13,7 +13,7 @@ #include "coreneuron/network/netcon.hpp" namespace coreneuron { -/// Mechanism type to be used from stdindex2ptr and nrn_dblpntr2nrncore (in Neuron) +/// Mechanism type to be used from legacy_index2pointer and nrn_dblpntr2nrncore (in Neuron) /// Values of the mechanism types should be negative numbers to avoid any conflict with /// mechanism types of Memb_list(>0) or time(0) passed from Neuron enum mech_type { voltage = -1, i_membrane_ = -2 }; @@ -37,7 +37,7 @@ extern void mk_mech(const char* path); extern void set_globals(const char* path, bool cli_global_seed, int cli_global_seed_value); extern void mk_netcvode(void); extern void nrn_p_construct(void); -extern double* stdindex2ptr(int mtype, int index, NrnThread&); +extern double* legacy_index2pointer(int mtype, int index, NrnThread&); extern void delete_trajectory_requests(NrnThread&); extern void nrn_cleanup(); extern void nrn_cleanup_ion_map(); diff --git a/src/coreneuron/permute/node_permute.cpp b/src/coreneuron/permute/node_permute.cpp index d79d3ce44a..a19230b4fc 100644 --- a/src/coreneuron/permute/node_permute.cpp +++ b/src/coreneuron/permute/node_permute.cpp @@ -402,26 +402,6 @@ void permute_ml(Memb_list* ml, int type, NrnThread& nt) { update_pdata_values(ml, type, nt); } - -int nrn_index_permute(int ix, int type, Memb_list* ml) { - int* p = ml->_permute; - if (!p) { - return ix; - } - int layout = corenrn.get_mech_data_layout()[type]; - if (layout == Layout::AoS) { - int sz = corenrn.get_prop_param_size()[type]; - int i_cnt = ix / sz; - int i_sz = ix % sz; - return p[i_cnt] * sz + i_sz; - } else { - assert(layout == Layout::SoA); - int padded_cnt = nrn_soa_padded_size(ml->nodecount, layout); - int i_cnt = ix % padded_cnt; - int i_sz = ix / padded_cnt; - return i_sz * padded_cnt + p[i_cnt]; - } -} #endif // CORENRN_BUILD #if CORENRN_DEBUG diff --git a/src/coreneuron/permute/node_permute.h b/src/coreneuron/permute/node_permute.h index 541ebb73fd..fb08c6b000 100644 --- a/src/coreneuron/permute/node_permute.h +++ b/src/coreneuron/permute/node_permute.h @@ -42,7 +42,6 @@ void permute_ptr(int* vec, int n, int* permute); void permute_data(double* vec, int n, int* permute); void permute_ml(Memb_list* ml, int type, NrnThread& nt); -int nrn_index_permute(int, int type, Memb_list* ml); int* inverse_permute(int* p, int n); diff --git a/src/coreneuron/utils/nrnoc_aux.cpp b/src/coreneuron/utils/nrnoc_aux.cpp index 6d51dbe1f6..d9ba40fd1a 100644 --- a/src/coreneuron/utils/nrnoc_aux.cpp +++ b/src/coreneuron/utils/nrnoc_aux.cpp @@ -21,7 +21,7 @@ int v_structure_change; int diam_changed; #define MAXERRCOUNT 5 int hoc_errno_count; -const char* bbcore_write_version = "1.7"; // NMODLRandom +const char* bbcore_write_version = "1.8"; // Include ArrayDims char* pnt_name(Point_process* pnt) { return corenrn.get_memb_func(pnt->_type).sym; diff --git a/src/nmodl/nocpout.cpp b/src/nmodl/nocpout.cpp index 48dd954a0e..092ee6f412 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -184,6 +184,7 @@ static Item* net_send_delivered_; /* location for if flag is 1 then clear the pvarcount indexes pointers to variables such as ena */ static int varcount, parraycount; +static int prop_size; static std::vector> ppvar_data_field_strings; static std::vector data_field_strings; @@ -321,7 +322,7 @@ void parout() { Lappendstr(defs_list, "extern double *hoc_getarg(int);\n"); nrndeclare(); - varcount = parraycount = 0; + varcount = parraycount = prop_size = 0; declare_p(); // iondef defined _nrn_mechanism_cache_range ioncount = iondef(&pointercount); /* first is _nd_area if point process */ @@ -1282,7 +1283,7 @@ extern void _cvode_abstol( Symbol**, double*, int);\n\n\ } register_data_fields.append(");\n"); lappendstr(defs_list, register_data_fields.c_str()); - Sprintf(buf, " hoc_register_prop_size(_mechtype, %d, %d);\n", parraycount, ppvar_cnt); + Sprintf(buf, " hoc_register_prop_size(_mechtype, %d, %d);\n", prop_size, ppvar_cnt); Lappendstr(defs_list, buf); if (watch_seen_) { Lappendstr(defs_list, " hoc_reg_watch_allocate(_mechtype, _watch_alloc);\n"); @@ -1799,6 +1800,9 @@ static void var_count(Symbol* s) { if (s->subtype & ARRAY) { field.append(", "); field.append(std::to_string(s->araydim)); + prop_size += s->araydim; + } else { + prop_size += 1; } // **ATTENTION** in AoS NEURON then parraycount was incremented by s->araydim if the variable // was an array. In SoA NEURON this is not done; the array dimension is communicated separately. diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 381f21f812..dfdfa77307 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -58,10 +58,18 @@ void write_memb_mech_types_direct(std::ostream& s) { for (int type = 2; type < n_memb_func; ++type) { const char* w = " "; Memb_func& mf = memb_func[type]; + Memb_list& ml = memb_list[type]; s << mf.sym->name << w << type << w << int(pnt_map[type]) << w // the pointtype, 0 means not a POINT_PROCESS << nrn_is_artificial_[type] << w << nrn_is_ion(type) << w << nrn_prop_param_size_[type] - << w << bbcore_dparam_size[type] << std::endl; + << w << bbcore_dparam_size[type] << w; + + int n_vars = ml.get_num_variables(); + s << n_vars; + for (size_t i = 0; i < n_vars; ++i) { + s << w << ml.get_array_dims(i); + } + s << std::endl; if (nrn_is_ion(type)) { s << nrn_ion_charge(mf.sym) << std::endl; @@ -140,7 +148,7 @@ void nrnthreads_all_weights_return(std::vector& weights) { /** @brief Return location for CoreNEURON to copy data into. * The type is mechanism type or special negative type for voltage, - * i_membrane_, or time. See coreneuron/io/nrn_setup.cpp:stdindex2ptr. + * i_membrane_, or time. See coreneuron/io/nrn_setup.cpp:legacy_index2pointer. * We allow coreneuron to copy to NEURON's AoS data as CoreNEURON knows * how its data is arranged (SoA and possibly permuted). * This function figures out the size (just for sanity check) @@ -386,6 +394,7 @@ int nrnthread_dat2_mech(int tid, int vdata_offset = cg.ml_vdata_offset[i]; int isart = nrn_is_artificial_[type]; int n = ml->nodecount; + int n_vars = ml->get_num_variables(); int sz = nrn_prop_param_size_[type]; // As the NEURON data is now transposed then for now always create a new @@ -395,8 +404,11 @@ int nrnthread_dat2_mech(int tid, data = new double[n * sz]; } for (auto instance = 0, k = 0; instance < n; ++instance) { - for (auto variable = 0; variable < sz; ++variable) { - data[k++] = ml->data(instance, variable); + for (int variable = 0; variable < n_vars; ++variable) { + auto array_dim = ml->get_array_dims(variable); + for (int array_index = 0; array_index < array_dim; ++array_index) { + data[k++] = ml->data(instance, variable, array_index); + } } } diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h index 8bc9941a21..bde4366977 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.h @@ -16,7 +16,7 @@ typedef struct core2nrn_callback_t { CNB f; } core2nrn_callback_t; -// Mechanism type to be used from stdindex2ptr (in CoreNeuron) and nrn_dblpntr2nrncore. +// Mechanism type to be used from legacy_index2pointer (in CoreNeuron) and nrn_dblpntr2nrncore. // Values of the mechanism types should be negative numbers to avoid any conflict with // mechanism types of Memb_list(>0) or time(0) passed to CoreNeuron enum mech_type { voltage = -1, i_membrane_ = -2 }; diff --git a/src/nrniv/nrncore_write/io/nrncore_io.cpp b/src/nrniv/nrncore_write/io/nrncore_io.cpp index 46e0913ce5..9e4a99d2af 100644 --- a/src/nrniv/nrncore_write/io/nrncore_io.cpp +++ b/src/nrniv/nrncore_write/io/nrncore_io.cpp @@ -22,7 +22,7 @@ extern NetCvode* net_cvode_instance; extern void (*nrnthread_v_transfer_)(NrnThread*); int chkpnt; -const char* bbcore_write_version = "1.7"; // NMODLRandom +const char* bbcore_write_version = "1.8"; // Include ArrayDims /// create directory with given path void create_dir_path(const std::string& path) { diff --git a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp index 9267bd0c96..8e4e2d4082 100644 --- a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp +++ b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp @@ -122,9 +122,10 @@ void nrnbbcore_register_mapping() { mapinfo.add_sec_mapping(gid, smap); } -// This function is related to stdindex2ptr in CoreNeuron to determine which values should -// be transferred from CoreNeuron. Types correspond to the value to be transferred based on -// mech_type enum or non-artificial cell mechanisms. +// This function is related to legacy_index2pointer in CoreNeuron to determine +// which values should be transferred from CoreNeuron. Types correspond to the +// value to be transferred based on mech_type enum or non-artificial cell +// mechanisms. // Limited to pointers to voltage, nt.node_sav_rhs_storage() (fast_imem value) or // data of non-artificial cell mechanisms. // Input double* and NrnThread. Output type and index. diff --git a/src/nrniv/partrans.cpp b/src/nrniv/partrans.cpp index a6779bad9e..53d138887e 100644 --- a/src/nrniv/partrans.cpp +++ b/src/nrniv/partrans.cpp @@ -945,7 +945,7 @@ extern size_t nrnbbcore_gap_write(const char* path, int* group_ids); ntar // number of targets in this thread (vpre) nsrc // number of sources in this thread (v) - Note: type, index is sufficient for CoreNEURON stdindex2ptr to determine + Note: type, index is sufficient for CoreNEURON legacy_index2pointer to determine double* in its NrnThread.data array. src_sid // nsrc of these diff --git a/src/nrnoc/extcelln.cpp b/src/nrnoc/extcelln.cpp index 61eb0900a7..b6facf2b76 100644 --- a/src/nrnoc/extcelln.cpp +++ b/src/nrnoc/extcelln.cpp @@ -86,7 +86,8 @@ static void update_parmsize() { #endif ); // clang-format on - hoc_register_prop_size(EXTRACELL, nparm, 0); + int prop_size = nparm + 3 * (nrn_nlayer_extracellular - 1); + hoc_register_prop_size(EXTRACELL, prop_size, 0); } static std::vector param_default{ diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index ce86426495..57628839b7 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -874,10 +874,23 @@ void register_data_fields(int mechtype, register_data_fields(mechtype, params, dparams); } + +// Count the number of floating point variables. +// +// An array variable with N elements counts as N floating point variables. +static int count_prop_param_size(const std::vector>& param_info) { + int float_variables = 0; + for (const auto& [i, n]: param_info) { + float_variables += n; + } + + return float_variables; +} + void register_data_fields(int mechtype, std::vector> const& param_info, std::vector> const& dparam_info) { - nrn_prop_param_size_[mechtype] = param_info.size(); + nrn_prop_param_size_[mechtype] = count_prop_param_size(param_info); nrn_prop_dparam_size_[mechtype] = dparam_info.size(); delete[] std::exchange(memb_func[mechtype].dparam_semantics, nullptr); if (!dparam_info.empty()) { diff --git a/src/nrnoc/memblist.cpp b/src/nrnoc/memblist.cpp index 6e83477441..f8fe6677d1 100644 --- a/src/nrnoc/memblist.cpp +++ b/src/nrnoc/memblist.cpp @@ -53,6 +53,32 @@ neuron::container::data_handle Memb_list::data_handle( } +[[nodiscard]] int Memb_list::get_num_variables() const { + using Tag = neuron::container::Mechanism::field::FloatingPoint; + return m_storage->get_num_variables(); +} + +[[nodiscard]] int Memb_list::get_array_dims(int variable) const { + using Tag = neuron::container::Mechanism::field::FloatingPoint; + return m_storage->get_array_dims()[variable]; +} + +[[nodiscard]] int const* Memb_list::get_array_dims() const { + using Tag = neuron::container::Mechanism::field::FloatingPoint; + return m_storage->get_array_dims(); +} + +[[nodiscard]] int Memb_list::get_array_prefix_sums(int variable) const { + using Tag = neuron::container::Mechanism::field::FloatingPoint; + return m_storage->get_array_dim_prefix_sums()[variable]; +} + +[[nodiscard]] int const* Memb_list::get_array_prefix_sums() const { + using Tag = neuron::container::Mechanism::field::FloatingPoint; + return m_storage->get_array_dim_prefix_sums(); +} + + [[nodiscard]] std::ptrdiff_t Memb_list::legacy_index(double const* ptr) const { assert(m_storage_offset != neuron::container::invalid_row); // For a mechanism with (in order) range variables: a, b[2], c the mechanism data are diff --git a/src/nrnoc/nrnoc_ml.h b/src/nrnoc/nrnoc_ml.h index 6cf6d4397a..34e4134745 100644 --- a/src/nrnoc/nrnoc_ml.h +++ b/src/nrnoc/nrnoc_ml.h @@ -112,6 +112,33 @@ struct Memb_list { int variable, int array_index = 0) const; + + /** + * @brief Get the number of fields/variables of this mechanism. + */ + [[nodiscard]] int get_num_variables() const; + + /** + * @brief Get the array_dims of field `variable`. + */ + [[nodiscard]] int get_array_dims(int variable) const; + + /** + * @brief Get the array_dims of field `variable`. + */ + [[nodiscard]] int const* get_array_dims() const; + + /** + * @brief Get the array_dims of field `variable`. + */ + [[nodiscard]] int get_array_prefix_sums(int variable) const; + + /** + * @brief Get the array_dims of field `variable`. + */ + [[nodiscard]] int const* get_array_prefix_sums() const; + + /** * @brief Calculate a legacy index of the given pointer in this mechanism data. * diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 199de0a117..f5ac59824f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -676,6 +676,25 @@ if(NRN_ENABLE_PYTHON) ENVIRONMENT ${modtests_processor_env} ${nrnpython_mpi_env} COVERAGE_FILE=.coverage.coreneuron_test_natrans_py COMMAND ${modtests_launch_py} test/gjtests/test_natrans.py) + + foreach(run_mode RANGE 2) + nrn_add_test( + GROUP coreneuron_modtests + NAME array_variable_transfer_run_mode_${run_mode}_py_${processor} + REQUIRES coreneuron ${processor} ${modtests_preload_sanitizer} + SCRIPT_PATTERNS test/coreneuron/test_array_variables_transfer.py + ENVIRONMENT ${processor_env} NRN_TEST_RUN_MODE=${run_mode} NRN_TEST_FILE_MODE=false + COMMAND ${modtests_launch_py} test/coreneuron/test_array_variables_transfer.py) + endforeach() + + nrn_add_test( + GROUP coreneuron_modtests + NAME array_variable_transfer_file_mode_py_${processor} + REQUIRES coreneuron ${processor} ${modtests_preload_sanitizer} + SCRIPT_PATTERNS test/coreneuron/test_array_variables_transfer.py + ENVIRONMENT ${processor_env} NRN_TEST_RUN_MODE=0 NRN_TEST_FILE_MODE=true + COMMAND ${modtests_launch_py} test/coreneuron/test_array_variables_transfer.py) + if(NRN_ENABLE_MPI) nrn_find_python_module(MODULE mpi4py) if(mpi4py_FOUND) diff --git a/test/coreneuron/mod files/green.mod b/test/coreneuron/mod files/green.mod new file mode 100644 index 0000000000..2280da9387 --- /dev/null +++ b/test/coreneuron/mod files/green.mod @@ -0,0 +1,25 @@ +NEURON { + SUFFIX green + RANGE tau, upsilon +} + +DEFINE M 16 + +ASSIGNED { + tau + upsilon[M] +} + + +INITIAL { + FROM i = 0 TO M-1 { + upsilon[i] = 2.0 + 8*tau + } +} + +BREAKPOINT { + FROM i = 0 TO M-1 { + upsilon[i] = upsilon[i] + (i/3.0+1)*dt*cos((i/3.0+1) * t) + } +} + diff --git a/test/coreneuron/mod files/red.mod b/test/coreneuron/mod files/red.mod new file mode 100644 index 0000000000..c7b008c390 --- /dev/null +++ b/test/coreneuron/mod files/red.mod @@ -0,0 +1,25 @@ +NEURON { + SUFFIX red + RANGE tau, upsilon +} + +DEFINE M 16 + +ASSIGNED { + tau + upsilon[M] +} + + +INITIAL { + FROM i = 0 TO M-1 { + upsilon[i] = 0.0 + } +} + +BREAKPOINT { + FROM i = 0 TO M-1 { + upsilon[i] = sin((i + 1.0) * t) + } +} + diff --git a/test/coreneuron/test_array_variables_transfer.py b/test/coreneuron/test_array_variables_transfer.py new file mode 100644 index 0000000000..db06f53a19 --- /dev/null +++ b/test/coreneuron/test_array_variables_transfer.py @@ -0,0 +1,134 @@ +import itertools +import os + +import numpy as np + +from neuron import h, gui +from neuron import coreneuron +from neuron.tests.utils.strtobool import strtobool + +enable_coreneuron_option = bool( + strtobool(os.environ.get("NRN_TEST_ENABLE_CORENEURON", "true")) +) +enable_gpu_option = bool(strtobool(os.environ.get("CORENEURON_ENABLE_GPU", "false"))) +file_mode_option = bool(strtobool(os.environ.get("NRN_TEST_FILE_MODE", "false"))) +run_mode_option = os.environ.get("NRN_TEST_RUN_MODE", 2) +create_plots_option = bool(strtobool(os.environ.get("NRN_TEST_CREATE_PLOTS", "false"))) + + +def test_array_variable_transfer( + enable_coreneuron=enable_coreneuron_option, + enable_gpu=enable_gpu_option, + run_mode=run_mode_option, + file_mode=file_mode_option, + create_plots=create_plots_option, +): + + h("""create soma""") + h.soma.L = 5.6419 + h.soma.diam = 5.6419 + h.soma.insert("red") + h.soma.insert("green") + h.soma.nseg = 3 + + h.tstop = 6.0 + h.dt = 0.001 + + # TODO check replay. + + c_red, c_green = "red", "green" + m = 16 + + # `upsilon` is an array variable with at least `m` elements. It's value is + # approximately: + def upsilon(i, tau, c, t): + if c == c_red: + return np.sin((i + 1.0) * t) + elif c == c_green: + return 2.0 + 8 * tau + np.sin((i / 3.0 + 1) * t) + + cs = [c_green, c_red] + tols = [0.02, 1e-10] + + record_index = [0, m - 1] + taus = [0.25, 0.5, 0.75] + + i_tau_c_tol = list(itertools.product(record_index, taus, zip(cs, tols))) + i_tau_c = [(i, tau, c) for (i, tau, (c, tol)) in i_tau_c_tol] + tols = [tol for (_, _, (_, tol)) in i_tau_c_tol] + + t_vector = h.Vector().record(h._ref_t) + + for tau in taus: + h.soma(tau).tau_green = tau + + def record(i, tau, c): + if c == c_red: + return h.Vector().record(h.soma(tau)._ref_upsilon_red[i]) + elif c == c_green: + return h.Vector().record(h.soma(tau)._ref_upsilon_green[i]) + + upsilon_vector = [record(i, tau, c) for (i, tau, c) in i_tau_c] + + if enable_coreneuron: + pc = h.ParallelContext() + + # set gid for the cell (necessary for coreneuron data transfer) + pc.set_gid2node(pc.id() + 1, pc.id()) + myobj = h.NetCon(h.soma(0.5)._ref_v, None, sec=h.soma) + pc.cell(pc.id() + 1, myobj) + + with coreneuron(enable=enable_coreneuron, file_mode=file_mode): + h.stdinit() + + if run_mode == 0: + pc.psolve(h.tstop) + elif run_mode == 1: + while h.t < h.tstop: + pc.psolve(h.t + 1.0) + else: + while h.t < h.tstop: + h.continuerun(h.t + 0.5) + pc.psolve(h.t + 0.5) + + else: + h.stdinit() + h.run() + + t = np.array(t_vector.as_numpy()) + + assert t.size > 0, "No time instances recorded." + + upsilon_approx = [np.array(u.as_numpy()) for u in upsilon_vector] + upsilon_exact = [upsilon(i, tau, c, t) for (i, tau, c) in i_tau_c] + + if create_plots: + # Only import `matplotlib` if needed, it's not available + # during CI. + import matplotlib.pyplot as plt + + for k, u in enumerate(upsilon_exact): + legend_kwargs = {"label": "exact"} if k == 0 else dict() + plt.plot(t, u, "-k", linewidth=2, **legend_kwargs) + + for u in upsilon_approx: + plt.plot(t, u, "--", linewidth=2) + + plt.xlabel("time") + plt.ylabel("upsilon") + plt.title(f"Mode {run_mode}, File mode = {file_mode}, GPU = {enable_gpu}") + plt.savefig( + f"upsilon_traces-mode{run_mode}_filemode{file_mode}_gpu{enable_gpu}.png", + dpi=300, + ) + + for k, (tol, u_exact, u_approx) in enumerate( + zip(tols, upsilon_exact, upsilon_approx) + ): + abs_err_inf = np.max(np.abs(u_approx - u_exact)) + rel_err_inf = abs_err_inf / np.max(np.abs(u_exact)) + assert rel_err_inf < tol, f"{k}: {rel_err_inf} < {tol} failed." + + +if __name__ == "__main__": + test_array_variable_transfer() From 63053bd9865a5057e21280b7e3026567cda381d1 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 22 Apr 2024 11:53:59 +0200 Subject: [PATCH 42/62] Generate only one file for cmake_nrnconf.h (#2845) --- cmake/ConfigFileSetting.cmake | 1 - src/modlunit/consist.cpp | 2 +- src/modlunit/declare.cpp | 2 +- src/modlunit/init.cpp | 2 +- src/modlunit/io.cpp | 2 +- src/modlunit/kinunit.cpp | 2 +- src/modlunit/lex.lpp | 2 +- src/modlunit/list.cpp | 2 +- src/modlunit/model.cpp | 2 +- src/modlunit/nrnunit.cpp | 2 +- src/modlunit/parse1.ypp | 2 +- src/modlunit/passn.cpp | 2 +- src/modlunit/symbol.cpp | 2 +- src/modlunit/units.cpp | 2 +- src/modlunit/units1.cpp | 2 +- src/modlunit/version.cpp | 2 +- src/nmodl/consist.cpp | 2 +- src/nmodl/deriv.cpp | 2 +- src/nmodl/diffeq.ypp | 2 +- src/nmodl/discrete.cpp | 2 +- src/nmodl/init.cpp | 2 +- src/nmodl/io.cpp | 2 +- src/nmodl/kinetic.cpp | 2 +- src/nmodl/lex.lpp | 2 +- src/nmodl/list.cpp | 2 +- src/nmodl/modl.cpp | 2 +- src/nmodl/netrec_discon.cpp | 2 +- src/nmodl/noccout.cpp | 2 +- src/nmodl/nocpout.cpp | 2 +- src/nmodl/parsact.cpp | 2 +- src/nmodl/parse1.ypp | 2 +- src/nmodl/simultan.cpp | 2 +- src/nmodl/solve.cpp | 2 +- src/nmodl/symbol.cpp | 2 +- src/nmodl/units.cpp | 2 +- src/nmodl/version.cpp | 2 +- 36 files changed, 35 insertions(+), 36 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 9a44ce8c94..31fbbc7360 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -171,7 +171,6 @@ list(TRANSFORM version_strs APPEND "\"") list(TRANSFORM version_strs PREPEND "\"") string(JOIN ", " NRN_DYNAMIC_PYTHON_LIST_OF_VERSION_STRINGS ${version_strs}) nrn_configure_dest_src(nrnconf.h . cmake_nrnconf.h .) -nrn_configure_dest_src(nmodlconf.h . cmake_nrnconf.h .) nrn_configure_file(nrnmpiuse.h src/oc) nrn_configure_file(nrnconfigargs.h src/nrnoc) nrn_configure_file(nrnneosm.h src/nrncvode) diff --git a/src/modlunit/consist.cpp b/src/modlunit/consist.cpp index 6e2623a970..a89b5c63ec 100644 --- a/src/modlunit/consist.cpp +++ b/src/modlunit/consist.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/consist.c,v 1.2 1995/09/05 20:24:01 hines Exp */ /* diff --git a/src/modlunit/declare.cpp b/src/modlunit/declare.cpp index 22a4b066f6..29a0fe6d3c 100644 --- a/src/modlunit/declare.cpp +++ b/src/modlunit/declare.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include #include "model.h" diff --git a/src/modlunit/init.cpp b/src/modlunit/init.cpp index 80250d47ab..7ccea7ca4c 100644 --- a/src/modlunit/init.cpp +++ b/src/modlunit/init.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/init.c,v 1.9 1998/03/25 14:33:55 hines Exp */ #include "model.h" diff --git a/src/modlunit/io.cpp b/src/modlunit/io.cpp index 05efb0c536..28e23759df 100644 --- a/src/modlunit/io.cpp +++ b/src/modlunit/io.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/io.c,v 1.2 1997/11/24 16:19:09 hines Exp */ /* file.mod input routines */ diff --git a/src/modlunit/kinunit.cpp b/src/modlunit/kinunit.cpp index 003cf4cec0..ad41d5a109 100644 --- a/src/modlunit/kinunit.cpp +++ b/src/modlunit/kinunit.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "model.h" #include "symbol.h" #include "units.h" diff --git a/src/modlunit/lex.lpp b/src/modlunit/lex.lpp index ebe4320d08..f74a58afd6 100755 --- a/src/modlunit/lex.lpp +++ b/src/modlunit/lex.lpp @@ -15,7 +15,7 @@ #undef input #endif -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "model.h" #include "parse1.hpp" diff --git a/src/modlunit/list.cpp b/src/modlunit/list.cpp index 25c69f1bfd..e6bfac1b06 100644 --- a/src/modlunit/list.cpp +++ b/src/modlunit/list.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/list.c,v 1.3 1997/11/24 16:19:10 hines Exp */ /* The following routines support the concept of a list. diff --git a/src/modlunit/model.cpp b/src/modlunit/model.cpp index 3ae156cce5..04ff800ea8 100644 --- a/src/modlunit/model.cpp +++ b/src/modlunit/model.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/model.c,v 1.6 1998/07/12 13:19:02 hines Exp */ /* diff --git a/src/modlunit/nrnunit.cpp b/src/modlunit/nrnunit.cpp index 035beb2a94..9ee6a969e7 100644 --- a/src/modlunit/nrnunit.cpp +++ b/src/modlunit/nrnunit.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include "model.h" #include "units.h" diff --git a/src/modlunit/parse1.ypp b/src/modlunit/parse1.ypp index a10bf05f88..1b63690297 100755 --- a/src/modlunit/parse1.ypp +++ b/src/modlunit/parse1.ypp @@ -1,7 +1,7 @@ %{ /* /local/src/master/nrn/src/modlunit/parse1.y,v 1.11 1999/02/27 21:13:50 hines Exp */ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include #include "model.h" diff --git a/src/modlunit/passn.cpp b/src/modlunit/passn.cpp index 7c26668246..1456404f22 100644 --- a/src/modlunit/passn.cpp +++ b/src/modlunit/passn.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/passn.c,v 1.1.1.1 1994/10/12 17:22:50 hines Exp */ /* Returns parse tokens in same order that lexical analyzer did */ diff --git a/src/modlunit/symbol.cpp b/src/modlunit/symbol.cpp index bc23e79ccc..e59bad1b16 100644 --- a/src/modlunit/symbol.cpp +++ b/src/modlunit/symbol.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/symbol.c,v 1.1.1.1 1994/10/12 17:22:50 hines Exp */ #include diff --git a/src/modlunit/units.cpp b/src/modlunit/units.cpp index 5f67ca1d2b..9901f19fae 100644 --- a/src/modlunit/units.cpp +++ b/src/modlunit/units.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/units.c,v 1.5 1997/11/24 16:19:13 hines Exp */ /* Mostly from Berkeley */ #include "model.h" diff --git a/src/modlunit/units1.cpp b/src/modlunit/units1.cpp index 876d4590f5..7db0ba3f08 100644 --- a/src/modlunit/units1.cpp +++ b/src/modlunit/units1.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/units1.c,v 1.1.1.1 1994/10/12 17:22:51 hines Exp */ /* Just a connection to units.c so that file doesn't need to include modl.h */ #include "model.h" diff --git a/src/modlunit/version.cpp b/src/modlunit/version.cpp index 4d4247e766..4f7e71e288 100644 --- a/src/modlunit/version.cpp +++ b/src/modlunit/version.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/modlunit/version.c,v 1.1.1.1 1994/10/12 17:22:51 hines Exp */ const char* RCS_version = "1.1.1.1"; diff --git a/src/nmodl/consist.cpp b/src/nmodl/consist.cpp index 729796f83a..295fdca9b3 100644 --- a/src/nmodl/consist.cpp +++ b/src/nmodl/consist.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* * Check that names do not have conflicting types. This is done after the diff --git a/src/nmodl/deriv.cpp b/src/nmodl/deriv.cpp index 4071ef0e63..07ca2258c3 100644 --- a/src/nmodl/deriv.cpp +++ b/src/nmodl/deriv.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "modl.h" #include "symbol.h" diff --git a/src/nmodl/diffeq.ypp b/src/nmodl/diffeq.ypp index 462eb98510..3d316efe91 100755 --- a/src/nmodl/diffeq.ypp +++ b/src/nmodl/diffeq.ypp @@ -6,7 +6,7 @@ The only thing that makes this less than elegant is dealing with 0.0 */ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include "modl.h" #include "difeqdef.h" diff --git a/src/nmodl/discrete.cpp b/src/nmodl/discrete.cpp index 0051132b70..055f9492cc 100644 --- a/src/nmodl/discrete.cpp +++ b/src/nmodl/discrete.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include "modl.h" diff --git a/src/nmodl/init.cpp b/src/nmodl/init.cpp index b5c89c3c33..394e3f8b94 100644 --- a/src/nmodl/init.cpp +++ b/src/nmodl/init.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/nmodl/init.c,v 4.5 1998/03/25 14:33:42 hines Exp */ #include "modl.h" diff --git a/src/nmodl/io.cpp b/src/nmodl/io.cpp index 88110a1b36..9c58054348 100644 --- a/src/nmodl/io.cpp +++ b/src/nmodl/io.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* file.mod input routines */ #include diff --git a/src/nmodl/kinetic.cpp b/src/nmodl/kinetic.cpp index b3f457355d..763a4b9971 100644 --- a/src/nmodl/kinetic.cpp +++ b/src/nmodl/kinetic.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #define Glass 1 diff --git a/src/nmodl/lex.lpp b/src/nmodl/lex.lpp index d7dc282531..4ec229210f 100755 --- a/src/nmodl/lex.lpp +++ b/src/nmodl/lex.lpp @@ -1,7 +1,7 @@ %{ /* /local/src/master/nrn/src/nmodl/lex.lpp,v 4.2 1997/11/05 17:59:02 hines Exp */ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #undef output #undef unput diff --git a/src/nmodl/list.cpp b/src/nmodl/list.cpp index 807d6547e5..0e373fab5a 100644 --- a/src/nmodl/list.cpp +++ b/src/nmodl/list.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* The following routines support the concept of a list. That is, one can insert at the head of a list or append to the tail of a diff --git a/src/nmodl/modl.cpp b/src/nmodl/modl.cpp index 9523c7a2a1..29839db133 100644 --- a/src/nmodl/modl.cpp +++ b/src/nmodl/modl.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* * int main(int argc, char *argv[]) --- returns 0 if translation is diff --git a/src/nmodl/netrec_discon.cpp b/src/nmodl/netrec_discon.cpp index 4666bf0356..f4dd412d70 100644 --- a/src/nmodl/netrec_discon.cpp +++ b/src/nmodl/netrec_discon.cpp @@ -51,7 +51,7 @@ that only dsi/dt that is affected by sj will change si. */ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include #include diff --git a/src/nmodl/noccout.cpp b/src/nmodl/noccout.cpp index f95ed6e315..f57fb52e04 100644 --- a/src/nmodl/noccout.cpp +++ b/src/nmodl/noccout.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* print the .c file from the lists */ #include "modl.h" diff --git a/src/nmodl/nocpout.cpp b/src/nmodl/nocpout.cpp index 092ee6f412..abf2dce50f 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/nmodl/nocpout.c,v 4.1 1997/08/30 20:45:28 hines Exp */ diff --git a/src/nmodl/parsact.cpp b/src/nmodl/parsact.cpp index 79e8b96584..e6d656063f 100644 --- a/src/nmodl/parsact.cpp +++ b/src/nmodl/parsact.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* * some parse actions to reduce size of parse.ypp the installation routines can diff --git a/src/nmodl/parse1.ypp b/src/nmodl/parse1.ypp index 03c7108c46..37076da3bd 100755 --- a/src/nmodl/parse1.ypp +++ b/src/nmodl/parse1.ypp @@ -1,7 +1,7 @@ %{ /* /local/src/master/nrn/src/nmodl/parse1.ypp,v 4.11 1999/03/24 18:34:08 hines Exp */ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "modl.h" #include diff --git a/src/nmodl/simultan.cpp b/src/nmodl/simultan.cpp index a946a334cc..ef649b414c 100644 --- a/src/nmodl/simultan.cpp +++ b/src/nmodl/simultan.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "modl.h" #include "parse1.hpp" #include "symbol.h" diff --git a/src/nmodl/solve.cpp b/src/nmodl/solve.cpp index 9051da0f49..9406a74a00 100644 --- a/src/nmodl/solve.cpp +++ b/src/nmodl/solve.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* /local/src/master/nrn/src/nmodl/solve.c,v 4.4 1998/08/20 21:07:34 hines Exp */ #include "modl.h" diff --git a/src/nmodl/symbol.cpp b/src/nmodl/symbol.cpp index 11c0fedf9f..04a970a5e6 100644 --- a/src/nmodl/symbol.cpp +++ b/src/nmodl/symbol.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> #include "modl.h" #include "parse1.hpp" diff --git a/src/nmodl/units.cpp b/src/nmodl/units.cpp index 698fb51f60..a618b6e73b 100755 --- a/src/nmodl/units.cpp +++ b/src/nmodl/units.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* * Automake doesn't deal well with sources that live in other directories. * This is a quick and dirty workaround. diff --git a/src/nmodl/version.cpp b/src/nmodl/version.cpp index 207745ec5d..a40e4a4a2e 100644 --- a/src/nmodl/version.cpp +++ b/src/nmodl/version.cpp @@ -1,4 +1,4 @@ -#include <../../nmodlconf.h> +#include <../../nrnconf.h> /* $Header$ */ const char* RCS_version = "$Revision: 1098 $"; const char* RCS_date = "$Date: 2005-10-04 22:55:37 +0200 (Tue, 04 Oct 2005) $"; From 82b6996eb44b75b7ddb3a3b2423c6dad588472bd Mon Sep 17 00:00:00 2001 From: MikeG Date: Mon, 22 Apr 2024 14:41:12 +0200 Subject: [PATCH 43/62] Cleanup remove old defines (#2843) --- src/ivoc/ivocvect.cpp | 18 ------------------ src/nrniv/nrnmenu.cpp | 4 ---- src/oc/audit.cpp | 8 +------- src/oc/debug.cpp | 4 ---- src/oc/x.cpp | 4 ---- src/sparse13/spdefs.h | 14 -------------- src/sparse13/spfactor.cpp | 25 ------------------------- 7 files changed, 1 insertion(+), 76 deletions(-) diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index 866fab6836..cf72e1c69b 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -1,6 +1,5 @@ #include <../../nrnconf.h> -//#include #include #include #include @@ -24,15 +23,10 @@ #include #include #include -//#include #include #endif -#if defined(SVR4) -extern void exit(int status); -#endif - #include "classreg.h" #if HAVE_IV #include "apwindow.h" @@ -48,24 +42,12 @@ extern void exit(int status); #endif #define PI M_PI #endif -#define BrainDamaged 0 // The Sun CC compiler but it doesn't hurt to leave it in -#if BrainDamaged -#define FWrite(arg1, arg2, arg3, arg4) \ - if (fwrite((arg1), arg2, arg3, arg4) != arg3) { \ - hoc_execerror("fwrite error", 0); \ - } -#define FRead(arg1, arg2, arg3, arg4) \ - if (fread((arg1), arg2, arg3, arg4) != arg3) { \ - hoc_execerror("fread error", 0); \ - } -#else #define FWrite(arg1, arg2, arg3, arg4) \ if (fwrite(arg1, arg2, arg3, arg4) != arg3) { \ } #define FRead(arg1, arg2, arg3, arg4) \ if (fread(arg1, arg2, arg3, arg4) != arg3) { \ } -#endif /** * As all parameters are passed from hoc as double, we need diff --git a/src/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index 25342ae01a..22f3ccbc1a 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -79,10 +79,6 @@ void nrnsecmenu() { hoc_retpushx(1.); } -#ifdef ultrix -char* strstr(const char*, const char*); -#endif - static bool has_globals(const char* name) { Symbol* sp; char suffix[100]; diff --git a/src/oc/audit.cpp b/src/oc/audit.cpp index 33fedaceef..3b26128078 100644 --- a/src/oc/audit.cpp +++ b/src/oc/audit.cpp @@ -221,13 +221,7 @@ static void xopen_audit(void) { #endif } -#ifdef NeXT -int hoc_retrieve_audit(int id) /* I have no idea why... CMC */ -#else -int hoc_retrieve_audit(int id) - -#endif -{ +int hoc_retrieve_audit(int id) { #if !OCSMALL RetrieveAudit save; char buf[200]; diff --git a/src/oc/debug.cpp b/src/oc/debug.cpp index 415f5af9fd..a8b511eb6d 100644 --- a/src/oc/debug.cpp +++ b/src/oc/debug.cpp @@ -6,11 +6,7 @@ #include int zzdebug; -#if DOS -#define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", p, p->pf, c2) -#else #define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", p, p->pf, c2) -#endif void debug(void) /* print the machine */ { diff --git a/src/oc/x.cpp b/src/oc/x.cpp index 1f01a6d8f2..33c1cd8f90 100644 --- a/src/oc/x.cpp +++ b/src/oc/x.cpp @@ -7,10 +7,6 @@ #endif #endif -#if defined(__alpha) -#undef USG -#endif - #if NRNOC_X11 #if defined(IVX11_DYNAM) diff --git a/src/sparse13/spdefs.h b/src/sparse13/spdefs.h index f328b9d247..f7977c77ad 100644 --- a/src/sparse13/spdefs.h +++ b/src/sparse13/spdefs.h @@ -387,22 +387,8 @@ /* * MEMORY ALLOCATION */ -#if 1 #include "spmatrix.h" #include -#else -#if !defined(__MWERKS__) -extern char *malloc(), *calloc(), *realloc(); - -#ifdef ultrix -extern void free(); -extern void abort(); -#else -extern free(); -extern abort(); -#endif -#endif -#endif #define ALLOC(type, number) ((type*)malloc((unsigned)(sizeof(type) * (number)))) #define REALLOC(ptr, type, number) \ diff --git a/src/sparse13/spfactor.cpp b/src/sparse13/spfactor.cpp index c1d04bda2f..c3f960f6f4 100644 --- a/src/sparse13/spfactor.cpp +++ b/src/sparse13/spfactor.cpp @@ -639,36 +639,11 @@ void spPartition(char* eMatrix, int Mode) * No is the number of operations in the inner loop. */ -#define generic -#ifdef hp9000s300 -#if REAL - DoRealDirect[Step] = (Nm[Step] + No[Step] > 3 * Nc[Step] - 2 * Nm[Step]); -#endif -#if spCOMPLEX - /* On the hp350, it is never profitable to use direct for complex. */ - DoCmplxDirect[Step] = NO; -#endif -#undef generic -#endif - -#ifdef vax #if REAL DoRealDirect[Step] = (Nm[Step] + No[Step] > 3 * Nc[Step] - 2 * Nm[Step]); #endif #if spCOMPLEX DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7 * Nc[Step] - 4 * Nm[Step]); -#endif -#undef generic -#endif - -#ifdef generic -#if REAL - DoRealDirect[Step] = (Nm[Step] + No[Step] > 3 * Nc[Step] - 2 * Nm[Step]); -#endif -#if spCOMPLEX - DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7 * Nc[Step] - 4 * Nm[Step]); -#endif -#undef generic #endif } From fbe4bb2d28a1aa8f973aa77d1718e7444912e48c Mon Sep 17 00:00:00 2001 From: MikeG Date: Mon, 22 Apr 2024 16:04:06 +0200 Subject: [PATCH 44/62] Delete unused files (#2847) --- src/gnu/neuron_gnu_std.h | 29 ----- src/ivoc/ivocmac.cpp | 264 --------------------------------------- src/ivoc/macmain.cpp | 7 -- src/mswin/mwprefix.h | 39 ------ src/oc/macprt.cpp | 183 --------------------------- 5 files changed, 522 deletions(-) delete mode 100755 src/gnu/neuron_gnu_std.h delete mode 100644 src/ivoc/ivocmac.cpp delete mode 100644 src/ivoc/macmain.cpp delete mode 100644 src/mswin/mwprefix.h delete mode 100644 src/oc/macprt.cpp diff --git a/src/gnu/neuron_gnu_std.h b/src/gnu/neuron_gnu_std.h deleted file mode 100755 index 26ffb73449..0000000000 --- a/src/gnu/neuron_gnu_std.h +++ /dev/null @@ -1,29 +0,0 @@ -// This may look like C code, but it is really -*- C++ -*- -/* -Copyright (C) 1988, 1992 Free Software Foundation - written by Doug Lea (dl@rocky.oswego.edu) - -This file is part of the GNU C++ Library. This library is free -software; you can redistribute it and/or modify it under the terms of -the GNU Library General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. This library is distributed in the hope -that it will be useful, but WITHOUT ANY WARRANTY; without even the -implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU Library General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -#pragma once -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include -#include diff --git a/src/ivoc/ivocmac.cpp b/src/ivoc/ivocmac.cpp deleted file mode 100644 index 0ebc0345d4..0000000000 --- a/src/ivoc/ivocmac.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include <../../nrnconf.h> - -#include - - -#include -#include "apwindow.h" -#include "ivoc.h" -#include "rubband.h" -#include "symdir.h" -#include "oc2iv.h" -#include "graph.h" -#include -#include -#include -#include -#include - -typedef void (*NrnBBSCallback)(const char*); - - -char* mktemp(char*) { - return NULL; -} - -bool nrnbbs_connect() { - return false; -} -void nrnbbs_disconnect() {} -bool nrnbbs_connected() { - return false; -} - -void nrnbbs_post(const char*) {} -void nrnbbs_post_int(const char*, int) {} -void nrnbbs_post_string(const char*, const char*) {} - -bool nrnbbs_take(const char*) { - return false; -} -bool nrnbbs_take_int(const char*, int*) { - return false; -} -bool nrnbbs_take_string(const char*, char*) { - return false; -} - -bool nrnbbs_look(const char*) { - return false; -} - -void nrnbbs_exec(const char*) {} - -void nrnbbs_notify(const char*, NrnBBSCallback) {} - -void nrnbbs_wait(bool* pflag = (bool*) 0) {} - -bool is_mac_dll(FSSpec*); -bool mac_open_dll(const char*, FSSpec*); - -bool is_mac_dll(FSSpec* fs) { - FInfo finfo; - FSpGetFInfo(fs, &finfo); - return finfo.fdType == 'shlb'; -} - -extern Symlist *hoc_symlist, *hoc_built_in_symlist; -extern OSErr __path2fss(const char* name, FSSpec*); -extern void hoc_nrn_load_dll(); - -static long fsspec2id(FSSpec* fs) { - CInfoPBRec ci; - Str255 name; - int i; - for (i = 0; i < 64; ++i) { - name[i] = fs->name[i]; - } - ci.hFileInfo.ioCompletion = 0; - ci.hFileInfo.ioNamePtr = name; - ci.hFileInfo.ioVRefNum = fs->vRefNum; - ci.hFileInfo.ioDirID = fs->parID; - ci.hFileInfo.ioFDirIndex = 0; - OSErr err = PBGetCatInfo(&ci, false); - return ci.hFileInfo.ioDirID; -} -static int ndll; -static long dllid[10]; - -bool mac_open_dll(const char* name, FSSpec* fs) { - CFragConnectionID id; - Ptr mainaddr; - Str255 sname; - int j; - long fid = fsspec2id(fs); - for (j = 0; j < ndll; ++j) { - if (dllid[j] == fid) { - printf("%s DLL already loaded\n", name); - return false; - } - } - dllid[ndll] = fid; - ndll = (ndll < 10) ? ndll + 1 : 10; - printf("Loading DLL %s\n", name); -#if 1 - OSErr myErr = GetDiskFragment(fs, 0, kCFragGoesToEOF, 0, kLoadCFrag, &id, &mainaddr, sname); - if (myErr) { - sname[sname[0] + 1] = '\0'; - printf("dll load error %d\n%s\n", myErr, sname + 1); - return false; - } - // printf("successfully loaded %s\n", name); - // printf("mainaddr=%p\n", mainaddr); - mainaddr = NULL; - long cnt; - myErr = CountSymbols(id, &cnt); - // printf("symbols exported = %d\n", cnt); - for (long i = 0; i < cnt; ++i) { - Ptr symaddr; - CFragSymbolClass symclass; - myErr = GetIndSymbol(id, i, sname, &symaddr, &symclass); - sname[sname[0] + 1] = '\0'; - if (strcmp((sname + 1), "main") == 0) { - mainaddr = symaddr; - } - // printf("symbol %d name %s\n", i, sname+1); - } -// printf("mainaddr=%p\n", mainaddr); -#if 1 - if (mainaddr) { - Symlist* sav = hoc_symlist; - hoc_symlist = hoc_built_in_symlist; - hoc_built_in_symlist = NULL; - (*(Pfri) mainaddr)(); - hoc_built_in_symlist = hoc_symlist; - hoc_symlist = sav; - return true; - } -#endif -#endif - return false; -} - -bool mac_load_dll(const char* name) { - FSSpec fss; - if ((__path2fss(name, &fss) != fnfErr) && is_mac_dll(&fss)) { - return mac_open_dll(name, &fss); - } - return false; -} - -void hoc_nrn_load_dll() { - int b = mac_load_dll(expand_env_var(gargstr(1))); - ret((double) b); -} - -void pwmimpl_redraw(Window* w) { - w->rep()->MACpaint(); -} - -void ivoc_bring_to_top(Window* w) { - BringToFront(w->rep()->macWindow()); -} - -//--------------------------------------------------------- - - -void Oc::cleanup() { - if (help_cursor_) { - delete help_cursor_; - } -} - -void PrintableWindow::hide() { - unmap(); -} - -void PrintableWindow::xmove(int x, int y) { - WindowPtr theWin = Window::rep()->macWindow(); - MoveWindow(theWin, (x + 1), (y + 17), true); -} -int PrintableWindow::xleft() const { - WindowRep& w = *Window::rep(); - if (w.bound()) { - GrafPtr oldPort; - GetPort(&oldPort); - WindowPtr theWin = w.macWindow(); - w.setport(); - Point upperLeft; - upperLeft.h = theWin->portRect.left; - upperLeft.v = theWin->portRect.top; - LocalToGlobal(&upperLeft); - SetPort(oldPort); - return upperLeft.h - 1; - } else { - return 0; - } -} -int PrintableWindow::xtop() const { - WindowRep& w = *Window::rep(); - if (w.bound()) { - GrafPtr oldPort; - GetPort(&oldPort); - WindowPtr theWin = w.macWindow(); - w.setport(); - Point upperLeft; - upperLeft.h = theWin->portRect.left; - upperLeft.v = theWin->portRect.top; - LocalToGlobal(&upperLeft); - SetPort(oldPort); - return upperLeft.v - 17; - } else { - return 0; - } -} - -void PrintableWindow::xplace(int x, int y) { - WindowRep& wr = *Window::rep(); - // printf("xplace %d %d %d\n", x, y,wr.bound()); - if (wr.bound()) { - xmove(x, y); - } else { - xplace_ = true; - xleft_ = x + 1; - xtop_ = y + 17; - } -} -void PrintableWindow::default_geometry() { - DismissableWindow::default_geometry(); - // the problem is that at this point the canvas size is not necessarly correct. - if (xplace_) { - pplace(xleft_, display()->pheight() - xtop_ - canvas()->pheight()); - } -} - -// following analogy to MACwindow::MACpaint -static CGrafPtr cg_; -static GDHandle gd_; - -void Rubberband::rubber_on(Canvas* c) { - // printf("Rubberband::rubber_on\n"); - // c->front_buffer(); - GetGWorld(&cg_, &gd_); - WindowPtr mw = c->window()->rep()->macWindow(); - SetGWorld((CGrafPort*) mw, GetMainDevice()); -} -void Rubberband::rubber_off(Canvas* c) { - // c->back_buffer(); - SetGWorld(cg_, gd_); - // printf("Rubberband::rubber_off\n"); -} - -IOHandler::IOHandler() {} -IOHandler::~IOHandler() {} -int IOHandler::inputReady(int) { - return 0; -} -int IOHandler::outputReady(int) { - return 0; -} -int IOHandler::exceptionRaised(int) { - return 0; -} -void IOHandler::timerExpired(long, long) {} -void IOHandler::childStatus(pid_t, int) {} diff --git a/src/ivoc/macmain.cpp b/src/ivoc/macmain.cpp deleted file mode 100644 index f944cf6cf3..0000000000 --- a/src/ivoc/macmain.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma import on -int ivocmain(int, const char**, const char**); -#pragma import off - -int main() { - return ivocmain(0, 0, 0); -} diff --git a/src/mswin/mwprefix.h b/src/mswin/mwprefix.h deleted file mode 100644 index 877b31f9ec..0000000000 --- a/src/mswin/mwprefix.h +++ /dev/null @@ -1,39 +0,0 @@ -/* auto include file for metrowerks codewarrior for all nrn */ -#include -#pragma once off -#ifndef __WIN32__ -#define __WIN32__ 1 -#endif -#ifndef WIN32 -#define WIN32 1 -#endif -#define _WIN32 -#ifndef _Windows -#define _Windows 1 -#endif -struct Section; -struct Object; -struct Symbol; -#define motif_kit -#define sgi_motif_kit -#define printf myprintf -#define vprintf myvprintf -#define gets mygets -#define puts myputs -#define fprintf myfprintf -#undef small -#undef near -#define small mysmall -#define near mynear - -#define stricmp _stricmp -#define putenv _putenv - -//#define system mysystem -#undef DELETE -#undef IGNORE -#define HOC 1 -#define OOP 1 -#define OC_CLASSES "nrnclass.h" -#define USECVODE 1 -#define USEMATRIX 1 diff --git a/src/oc/macprt.cpp b/src/oc/macprt.cpp deleted file mode 100644 index 683bb36a6b..0000000000 --- a/src/oc/macprt.cpp +++ /dev/null @@ -1,183 +0,0 @@ - -#include -#include -#include -#include -#include -#include "hoc.h" - -#include "gui-redirect.h" - -extern void debugfile(const char*, ...); -extern int oc_print_from_dll(char*); -extern void single_event_run(); - -extern char* neuron_home; - -int oc_print_from_dll(char* buf) { /* interchange \n and \r !*/ - char* cp; - for (cp = buf; *cp != '\0'; ++cp) { /* safe because buf is already a temp buffer */ - if (*cp == '\n') { - *cp = '\r'; - } else if (*cp == '\r') { - *cp = '\n'; - } - } - return printf("%s", buf); -} - -/* jijun 4/22/97, 4/23/97 */ -extern void setneuronhome(const char* p) { - CInfoPBRec myPB; - short vRefNum; - long dirID; - Str255 dirName; - char prePath[256]; - static char fullPath[256]; - - OSErr err = HGetVol((0), &vRefNum, &dirID); - if (err == noErr) { - myPB.dirInfo.ioNamePtr = dirName; - myPB.dirInfo.ioVRefNum = vRefNum; - myPB.dirInfo.ioDrParID = dirID; - myPB.dirInfo.ioFDirIndex = -1; - do { - myPB.dirInfo.ioDrDirID = myPB.dirInfo.ioDrParID; - err = PBGetCatInfoSync(&myPB); - if (err == noErr) { - dirName[dirName[0] + 1] = '\0'; - strcpy(prePath, &dirName[1]); - strcat(prePath, ":"); - strcat(prePath, fullPath); - strcpy(fullPath, prePath); - } - } while (myPB.dirInfo.ioDrDirID > 2); - } - - neuron_home = fullPath; - // get rid of last ':' - neuron_home[strlen(neuron_home) - 1] = '\0'; - // debugfile("neuron_home = %s\n", neuron_home); -} - -char* getenv(const char* s) { - static char buf[200]; - if (strcmp(s, "NEURONHOME") == 0) { - return neuron_home; - } - if (strcmp(s, "NRNDEMO") == 0) { - strcpy(buf, neuron_home); - strcat(buf, ":demo:"); - return buf; - } - printf("getenv: don't know |%s|\n", s); - return 0; -} - -int hoc_copyfile(const char* src, const char* dest) { - return 0; -} - -void hoc_check_intupt(int intupt) { -#if 1 - extern void set_intset(); - EventRecord e; - if (EventAvail(keyDownMask, &e)) { - // debugfile("%d\n", e.what); - if (e.what == keyDown) { - char c = e.message & charCodeMask; - if (c == 0x03) { - set_intset(); - } - } - // single_event_run(); - } -#endif -} - -FILE* popen(char* s1, char* s2) { - printf("no popen\n"); - return 0; -} - -pclose(FILE* p) { - printf("no pclose\n"); -} - -hoc_win_normal_cursor() {} - -hoc_win_wait_cursor() {} - -void plprint(const char* s) { - printf("%s", s); -} -int hoc_plttext; -/* -int getpid() { - return 1; -} -*/ -hoc_close_plot() {} -hoc_Graphmode() { - TRY_GUI_REDIRECT_DOUBLE("graphmode", NULL); - ret(); - pushx(0.); -} -hoc_Graph() { - TRY_GUI_REDIRECT_DOUBLE("graph", NULL); - ret(); - pushx(0.); -} -hoc_regraph() { - TRY_GUI_REDIRECT_DOUBLE("regraph", NULL); - ret(); - pushx(0.); -} -hoc_plotx() { - TRY_GUI_REDIRECT_DOUBLE("plotx", NULL); - ret(); - pushx(0.); -} -hoc_ploty() { - TRY_GUI_REDIRECT_DOUBLE("ploty", NULL); - ret(); - pushx(0.); -} -hoc_Plt() { - TRY_GUI_REDIRECT_DOUBLE("plt", NULL); - ret(); - pushx(0.); -} -hoc_Setcolor() { - TRY_GUI_REDIRECT_DOUBLE("setcolor", NULL); - ret(); - pushx(0.); -} -hoc_Lw() { - ret(); - pushx(0.); -} -hoc_settext() { - TRY_GUI_REDIRECT_DOUBLE("settext", NULL); - ret(); - pushx(0.); -} -hoc_Plot() { - TRY_GUI_REDIRECT_DOUBLE("plot", NULL); - ret(); - pushx(0.); -} -hoc_axis() { - TRY_GUI_REDIRECT_DOUBLE("axis", NULL); - ret(); - pushx(0.); -} - - -// int gethostname() {printf("no gethostname\n");} - - -plt(int mode, double x, double y) {} - - -initplot() {} From 8383628fecef9fc95232f324b2642780e9fc78c8 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 22 Apr 2024 23:07:42 +0200 Subject: [PATCH 45/62] Use fs::absolute instead of realpath (#2844) --- cmake/ConfigFileSetting.cmake | 1 - cmake_nrnconf.h.in | 3 --- src/nmodl/io.cpp | 13 +++++------ src/nmodl/modl.cpp | 13 +++++------ src/nmodl/nocpout.cpp | 16 ++++++++------ src/nrnoc/init.cpp | 41 +++++++++++------------------------ 6 files changed, 33 insertions(+), 54 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 31fbbc7360..89dc2f92b1 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -134,7 +134,6 @@ nrn_check_symbol_exists("mallinfo" "malloc.h" HAVE_MALLINFO) nrn_check_symbol_exists("mallinfo2" "malloc.h" HAVE_MALLINFO2) nrn_check_symbol_exists("mkstemp" "stdlib.h" HAVE_MKSTEMP) nrn_check_symbol_exists("posix_memalign" "stdlib.h" HAVE_POSIX_MEMALIGN) -nrn_check_symbol_exists("realpath" "stdlib.h" HAVE_REALPATH) nrn_check_symbol_exists("setenv" "stdlib.h" HAVE_SETENV) nrn_check_symbol_exists("setitimer" "sys/time.h" HAVE_SETITIMER) nrn_check_symbol_exists("sigaction" "signal.h" HAVE_SIGACTION) diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 105c942071..58f2b3e5b9 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -41,9 +41,6 @@ /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN -/* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH - /* Define to 1 if you have the `setenv' function. */ #undef HAVE_SETENV diff --git a/src/nmodl/io.cpp b/src/nmodl/io.cpp index 9c58054348..f6a0982ae6 100644 --- a/src/nmodl/io.cpp +++ b/src/nmodl/io.cpp @@ -1,4 +1,6 @@ #include <../../nrnconf.h> +#include +namespace fs = std::filesystem; /* file.mod input routines */ #include @@ -385,7 +387,6 @@ static FILE* include_open(char* fname, int err) { } void include_file(Item* q) { - char* pf = NULL; char fname[NRN_BUFSIZE]; Item* qinc; FileStackItem* fsi; @@ -415,13 +416,11 @@ void include_file(Item* q) { qinc = filetxtlist->prev; Sprintf(buf, ":::%s", STR(qinc)); replacstr(qinc, buf); -#if HAVE_REALPATH - pf = realpath(fname, NULL); -#endif - if (pf) { - Sprintf(buf, ":::realpath %s\n", pf); - free(pf); + try { + Sprintf(buf, ":::realpath %s\n", fs::absolute(fname).c_str()); lappendstr(filetxtlist, buf); + } catch (const std::filesystem::filesystem_error&) { + // If we are not able to get an absolute path from fname, simply avoid to write it. } } diff --git a/src/nmodl/modl.cpp b/src/nmodl/modl.cpp index 29839db133..0c23cb8748 100644 --- a/src/nmodl/modl.cpp +++ b/src/nmodl/modl.cpp @@ -151,17 +151,14 @@ int main(int argc, char** argv) { #endif if (nmodl_text) { Item* q; - char* pf{nullptr}; -#if HAVE_REALPATH && !defined(NRN_AVOID_ABSOLUTE_PATHS) - pf = realpath(finname, nullptr); -#endif fprintf( fcout, "\n#if NMODL_TEXT\nstatic void register_nmodl_text_and_filename(int mech_type) {\n"); - fprintf(fcout, " const char* nmodl_filename = \"%s\";\n", pf ? pf : finname); - if (pf) { - free(pf); - } +#if !defined(NRN_AVOID_ABSOLUTE_PATHS) + fprintf(fcout, " const char* nmodl_filename = \"%s\";\n", fs::absolute(finname).c_str()); +#else + fprintf(fcout, " const char* nmodl_filename = \"%s\";\n", finname); +#endif fprintf(fcout, " const char* nmodl_file_text = \n"); ITERATE(q, filetxtlist) { char* s = STR(q); diff --git a/src/nmodl/nocpout.cpp b/src/nmodl/nocpout.cpp index abf2dce50f..02c70c5a8e 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -71,6 +71,8 @@ directly by hoc. #ifdef HAVE_UNISTD_H #include #endif +#include +namespace fs = std::filesystem; #define GETWD(buf) getcwd(buf, NRN_BUFSIZE) int vectorize = 1; @@ -1401,14 +1403,14 @@ if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n\ " hoc_register_var(hoc_scdoub, hoc_vdoub, hoc_intfunc);\n"); { char buf1[NRN_BUFSIZE]; - char* pf{}; -#if HAVE_REALPATH && !defined(NRN_AVOID_ABSOLUTE_PATHS) - pf = realpath(finname, NULL); +#if !defined(NRN_AVOID_ABSOLUTE_PATHS) + Sprintf(buf1, + "\tivoc_help(\"help ?1 %s %s\\n\");\n", + mechname, + fs::absolute(finname).c_str()); +#else + Sprintf(buf1, "\tivoc_help(\"help ?1 %s %s\\n\");\n", mechname, finname); #endif - Sprintf(buf1, "\tivoc_help(\"help ?1 %s %s\\n\");\n", mechname, pf ? pf : finname); - if (pf) { - free(pf); - } Lappendstr(defs_list, buf1); } if (suffix[0]) { diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index 57628839b7..7b47891358 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -22,6 +22,8 @@ #include #include +#include +namespace fs = std::filesystem; /* change this to correspond to the ../nmodl/nocpout nmodl_version_ string*/ static char nmodl_version_[] = "7.7.0"; @@ -225,40 +227,23 @@ int nrn_is_cable(void) { } void* nrn_realpath_dlopen(const char* relpath, int flags) { - char* abspath = NULL; - void* handle = NULL; - - /* use realpath or _fullpath even if is already a full path */ - -#if defined(HAVE_REALPATH) - abspath = realpath(relpath, NULL); -#else /* not HAVE_REALPATH */ -#if defined(__MINGW32__) - abspath = _fullpath(NULL, relpath, 0); -#else /* not __MINGW32__ */ - abspath = strdup(relpath); -#endif /* not __MINGW32__ */ -#endif /* not HAVE_REALPATH */ - if (abspath) { - handle = dlopen(abspath, flags); + void* handle = nullptr; + try { // Try with an absolute path otherwise relpath + auto abspath = fs::absolute(relpath); + handle = dlopen(abspath.string().c_str(), flags); #if DARWIN if (!handle) { - nrn_possible_mismatched_arch(abspath); + nrn_possible_mismatched_arch(abspath.c_str()); } -#endif // DARWIN - free(abspath); - } else { - int patherr = errno; +#endif + } catch (const std::filesystem::filesystem_error& e) { handle = dlopen(relpath, flags); if (!handle) { - Fprintf(stderr, - "realpath failed errno=%d (%s) and dlopen failed with %s\n", - patherr, - strerror(patherr), - relpath); + std::cerr << "std::filesystem::absolute failed (" << e.what() + << ") and dlopen failed with '" << relpath << "'" << std::endl; #if DARWIN - nrn_possible_mismatched_arch(abspath); -#endif // DARWIN + nrn_possible_mismatched_arch(relpath); +#endif } } return handle; From 1adc8f5d803183a839e709872f2a590c0ece5620 Mon Sep 17 00:00:00 2001 From: Alexander Temerev Date: Tue, 23 Apr 2024 11:18:13 +0200 Subject: [PATCH 46/62] Random123 behavior tests (#2773) Included a smoke test to see if Random123 actually works (it is fully deterministic, so we should get exactly the same output for a particular set of parameters). --- test/coreneuron/unit/CMakeLists.txt | 1 + test/coreneuron/unit/random/CMakeLists.txt | 16 +++++++ test/coreneuron/unit/random/test_random.cpp | 52 +++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 test/coreneuron/unit/random/CMakeLists.txt create mode 100644 test/coreneuron/unit/random/test_random.cpp diff --git a/test/coreneuron/unit/CMakeLists.txt b/test/coreneuron/unit/CMakeLists.txt index 0b099c3eac..b21d48abd5 100644 --- a/test/coreneuron/unit/CMakeLists.txt +++ b/test/coreneuron/unit/CMakeLists.txt @@ -23,6 +23,7 @@ if(CORENRN_ENABLE_UNIT_TESTS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/alignment) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/queueing) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/solver) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/random) # lfp test uses nrnmpi_* wrappers but does not load the dynamic MPI library TODO: re-enable after # NEURON and CoreNEURON dynamic MPI are merged if(NOT NRN_ENABLE_MPI_DYNAMIC) diff --git a/test/coreneuron/unit/random/CMakeLists.txt b/test/coreneuron/unit/random/CMakeLists.txt new file mode 100644 index 0000000000..0c5effaa21 --- /dev/null +++ b/test/coreneuron/unit/random/CMakeLists.txt @@ -0,0 +1,16 @@ +# ============================================================================= +# Copyright (c) 2016 - 2024 Blue Brain Project/EPFL +# +# See top-level LICENSE file for details. +# ============================================================================= +if(${CMAKE_C_COMPILER_VERSION} VERSION_GREATER_EQUAL 21.11) + # Random123 does not play nicely with NVHPC 21.11+'s detection of ABM features, see: + # https://github.com/BlueBrain/CoreNeuron/issues/724 and + # https://github.com/DEShawResearch/random123/issues/6. + list(APPEND NRN_R123_COMPILE_DEFS R123_USE_INTRIN_H=0) +endif() +add_executable(random_test_bin test_random.cpp) +target_link_libraries(random_test_bin coreneuron-unit-test Catch2::Catch2WithMain) +target_compile_definitions(random_test_bin PRIVATE ${NRN_R123_COMPILE_DEFS}) +add_test(NAME random_test COMMAND $) +cpp_cc_configure_sanitizers(TARGET random_test_bin TEST random_test) diff --git a/test/coreneuron/unit/random/test_random.cpp b/test/coreneuron/unit/random/test_random.cpp new file mode 100644 index 0000000000..32db3435a6 --- /dev/null +++ b/test/coreneuron/unit/random/test_random.cpp @@ -0,0 +1,52 @@ +/* +# ============================================================================= +# Copyright (c) 2016 - 2024 Blue Brain Project/EPFL +# +# See top-level LICENSE file for details. +# =============================================================================. +*/ +#include +#include +#include "coreneuron/utils/randoms/nrnran123.h" + +using namespace coreneuron; + +TEST_CASE("random123 smoke test") { + const int SEED_KEY = 1; + const int NUM_STREAMS = 20; + const int NUM_SAMPLES = 1000; + nrnran123_State* rand_streams[NUM_STREAMS]; + + const int res_size = NUM_SAMPLES * NUM_STREAMS; + double res[res_size]; + + for (int i = 0; i < NUM_STREAMS; i++) { + rand_streams[i] = nrnran123_newstream(SEED_KEY, i); + nrnran123_setseq(rand_streams[i], 0, 0); + } + + nrn_pragma_omp(target teams distribute parallel for map(tofrom: res[0:res_size]) map(to: rand_streams[0:NUM_STREAMS])) + nrn_pragma_acc(parallel loop copy(res [0:res_size]) copyin(rand_streams [0:NUM_STREAMS])) + for (int i = 0; i < NUM_STREAMS; i++) { + for (int j = 0; j < NUM_SAMPLES; j++) { + double val = nrnran123_dblpick(rand_streams[i]); + res[i * NUM_SAMPLES + j] = val; + } + } + + // there should be no duplicates + + std::set check_set; + + for (int i = 0; i < NUM_STREAMS * NUM_SAMPLES; i++) { + double d = res[i]; + size_t old_size = check_set.size(); + check_set.insert(res[i]); + size_t new_size = check_set.size(); + + if (old_size == new_size) { + std::cerr << "Duplicate found! i = " << i << ", d = " << d << std::endl; + } + } + REQUIRE(check_set.size() == NUM_SAMPLES * NUM_STREAMS); +} \ No newline at end of file From b5f81deaf5e14ed8284583f556d84db13437c9c5 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Tue, 23 Apr 2024 14:15:33 -0700 Subject: [PATCH 47/62] fix some warnings (gcc 11.4.0) (#2851) * Remove useless re.compile --------- Co-authored-by: Nicolas Cornu --- src/nrniv/nrncore_write/io/nrncore_io.cpp | 6 +++--- src/oc/hoc.cpp | 4 +++- src/oc/mk_hocusr_h.py | 3 +-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/nrniv/nrncore_write/io/nrncore_io.cpp b/src/nrniv/nrncore_write/io/nrncore_io.cpp index 9e4a99d2af..9336221559 100644 --- a/src/nrniv/nrncore_write/io/nrncore_io.cpp +++ b/src/nrniv/nrncore_write/io/nrncore_io.cpp @@ -549,7 +549,7 @@ void nrn_write_mapping_info(const char* path, int gid, NrnMappingInfo& minfo) { /** number of gids in NrnThread */ int count; nrnthread_dat3_cell_count(count); - fprintf(f, "%zd\n", count); + fprintf(f, "%d\n", count); /** all cells mapping information in NrnThread */ for (size_t i = 0; i < count; i++) { @@ -559,7 +559,7 @@ void nrn_write_mapping_info(const char* path, int gid, NrnMappingInfo& minfo) { int n_seclist; nrnthread_dat3_cellmapping(i, cgid, t_sec, t_seg, n_seclist); /** gid, #section, #compartments, #sectionlists */ - fprintf(f, "%d %d %d %zd\n", cgid, t_sec, t_seg, n_seclist); + fprintf(f, "%d %d %d %d\n", cgid, t_sec, t_seg, n_seclist); for (size_t j = 0; j < n_seclist; j++) { std::string sclname; @@ -582,7 +582,7 @@ void nrn_write_mapping_info(const char* path, int gid, NrnMappingInfo& minfo) { data_lfp); /** section list name, number of sections, number of segments */ fprintf(f, - "%s %d %zd %zd %d\n", + "%s %d %d %zd %d\n", sclname.c_str(), nsec, nseg, diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 878f29b963..29ecd12c16 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -984,7 +984,9 @@ void hoc_final_exit(void) { std::string cmd{neuron_home}; cmd += "/lib/cleanup "; cmd += std::to_string(hoc_pid()); - system(cmd.c_str()); + if (system(cmd.c_str())) { // fix warning: ignoring return value + return; + } #endif } diff --git a/src/oc/mk_hocusr_h.py b/src/oc/mk_hocusr_h.py index 8d67a4d24a..596634c51a 100644 --- a/src/oc/mk_hocusr_h.py +++ b/src/oc/mk_hocusr_h.py @@ -25,8 +25,7 @@ def processvar(a, names): def remove_multiline_comments(string): # remove all occurance comments (/*COMMENT */) from string - string = re.sub(re.compile("/\*.*?\*/", re.DOTALL), "", string) - return string + return re.sub(r"/\*.*?\*/", "", string, 0, re.DOTALL) types = {} From 14f6b880b5efb358a0e84604acf4c8ba2252dbd3 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 24 Apr 2024 11:23:02 +0200 Subject: [PATCH 48/62] Replace `realpath` in CI scripts (#2835) Do not use `realpath` in scripts Old MacOS complains otherwise. Use an alternative with `readlink -f` --- .github/workflows/neuron-ci.yml | 6 +++--- bin/nrnivmodl-core.in | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index e39caea04f..9dcec6d953 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -108,12 +108,12 @@ jobs: # Unlink and re-link to prevent errors when GitHub macOS runner images # install Python outside of brew; See actions/setup-python#577 and BlueBrain/libsonata/pull/317 brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done - brew install ccache coreutils doxygen flex bison mpich ninja xz autoconf autoconf automake libtool + brew install ccache coreutils doxygen flex bison mpich ninja xz autoconf automake libtool # We use both for dynamic mpi in nrn brew unlink mpich brew install openmpi brew install --cask xquartz - echo /usr/local/opt/flex/bin:/usr/local/opt/bison/bin >> $GITHUB_PATH + echo "$(brew --prefix)/opt/flex/bin:$(brew --prefix)/opt/bison/bin" >> $GITHUB_PATH # Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources echo CMAKE_BUILD_PARALLEL_LEVEL=3 >> $GITHUB_ENV echo CTEST_PARALLEL_LEVEL=3 >> $GITHUB_ENV @@ -273,7 +273,7 @@ jobs: else CC=$(command -v clang-14) CXX=$(command -v clang++-14) - symbolizer_path=$(realpath $(command -v llvm-symbolizer-14)) + symbolizer_path="$(readlink -f "$(command -v llvm-symbolizer-14)")" cmake_args+=(-DLLVM_SYMBOLIZER_PATH="${symbolizer_path}") fi fi diff --git a/bin/nrnivmodl-core.in b/bin/nrnivmodl-core.in index 96726d4d9e..4668361cda 100755 --- a/bin/nrnivmodl-core.in +++ b/bin/nrnivmodl-core.in @@ -109,7 +109,7 @@ shopt -s nullglob if [ -d "$params_MODS_PATH" ]; then files=( "$params_MODS_PATH"/*.mod ) if [ ${#files} -eq 0 ]; then - echo "WARNING: No mod files found in '$(realpath ${params_MODS_PATH})', compiling default ones only!" + echo "WARNING: No mod files found in '$(readlink -f "${params_MODS_PATH}")', compiling default ones only!" fi else echo "FATAL: Invalid mods directory: '$params_MODS_PATH'" From 9acff56368a078c2e372e5d82523ec69fa568187 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 24 Apr 2024 17:45:50 +0200 Subject: [PATCH 49/62] Add missing include (#2852) --- src/neuron/container/soa_container.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/neuron/container/soa_container.hpp b/src/neuron/container/soa_container.hpp index 7b0f990c4d..c176281f26 100644 --- a/src/neuron/container/soa_container.hpp +++ b/src/neuron/container/soa_container.hpp @@ -5,6 +5,7 @@ #include "neuron/container/generic_data_handle.hpp" #include "neuron/container/soa_identifier.hpp" +#include // std::transform #include #include #include From b3672478a68d1742032312bd85c16968e88d8ef6 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 24 Apr 2024 17:48:11 +0200 Subject: [PATCH 50/62] Use configure_file instead of homemade macro (#2846) --- bin/CMakeLists.txt | 10 +-- cmake/ConfigFileSetting.cmake | 48 ++++++-------- cmake/MacroHelper.cmake | 45 ------------- cmake_nrnconf.h.in | 103 ++++++++++++++---------------- src/nrncvode/nrnneosm.h.in | 6 +- src/oc/nrnmpiuse.h.in | 15 ++--- src/sundials/sundials_config.h.in | 48 +++++++------- 7 files changed, 106 insertions(+), 169 deletions(-) diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index a60c5888f4..cd537ec88e 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -36,7 +36,7 @@ include(CMakeListsNrnMech) # ============================================================================= # nrnmech_makefile (based on coreneuron Configure templates) # ============================================================================= -nrn_configure_file(nrngui bin) +configure_file("nrngui.in" "nrngui" @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sortspike ${CMAKE_CURRENT_BINARY_DIR}/sortspike COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nrnivmodl_makefile_cmake.in ${PROJECT_BINARY_DIR}/bin/nrnmech_makefile @ONLY) @@ -49,10 +49,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nrnpyenv.sh.in ${PROJECT_BINARY_DIR}/ # file(CHMOD ...) and v3.20+ support setting permissions directly in configure_file(...). set(NRN_CONFIG_EXE_FILES "nrnivmodl" "neurondemo") foreach(NRN_CONFIG_EXE_FILE ${NRN_CONFIG_EXE_FILES}) - nrn_configure_dest_src(${NRN_CONFIG_EXE_FILE} bin/tmp ${NRN_CONFIG_EXE_FILE} bin) + configure_file("${NRN_CONFIG_EXE_FILE}.in" "tmp/${NRN_CONFIG_EXE_FILE}" @ONLY) file( - COPY ${PROJECT_BINARY_DIR}/bin/tmp/${NRN_CONFIG_EXE_FILE} - DESTINATION ${PROJECT_BINARY_DIR}/bin + COPY "${CMAKE_CURRENT_BINARY_DIR}/tmp/${NRN_CONFIG_EXE_FILE}" + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}" FILE_PERMISSIONS OWNER_READ OWNER_WRITE @@ -62,7 +62,7 @@ foreach(NRN_CONFIG_EXE_FILE ${NRN_CONFIG_EXE_FILES}) WORLD_READ WORLD_EXECUTE) endforeach() -file(REMOVE_RECURSE ${PROJECT_BINARY_DIR}/bin/tmp) +file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/bin/tmp") # ============================================================================= # Install targets diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 89dc2f92b1..7243972f37 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -155,13 +155,6 @@ nrn_check_type_exists(sys/types.h uid_t int uid_t) # ============================================================================= nrn_check_signal_return_type(RETSIGTYPE) -# ============================================================================= -# Copy cmake specific template files -# ============================================================================= -# nrnconf.h.in and nmodlconf.h.in were originally generated from config.h.in generated by -# autoheader. We use repository copy cmake_nrnconf.h.in to create nrnconf.h and nmodlconf.h directly -# in the PROJECT_BINARY_DIR from the nrn_configure_dest_src macro. - # ============================================================================= # Generate file from file.in template # ============================================================================= @@ -169,39 +162,40 @@ set(version_strs ${NRN_PYTHON_VERSIONS}) list(TRANSFORM version_strs APPEND "\"") list(TRANSFORM version_strs PREPEND "\"") string(JOIN ", " NRN_DYNAMIC_PYTHON_LIST_OF_VERSION_STRINGS ${version_strs}) -nrn_configure_dest_src(nrnconf.h . cmake_nrnconf.h .) -nrn_configure_file(nrnmpiuse.h src/oc) -nrn_configure_file(nrnconfigargs.h src/nrnoc) -nrn_configure_file(nrnneosm.h src/nrncvode) -nrn_configure_file(sundials_config.h src/sundials) -nrn_configure_dest_src(nrn.defaults share/nrn/lib nrn.defaults share/lib) +configure_file("${PROJECT_SOURCE_DIR}/cmake_nrnconf.h.in" "${PROJECT_BINARY_DIR}/nrnconf.h" @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/src/oc/nrnmpiuse.h.in" + "${PROJECT_BINARY_DIR}/src/oc/nrnmpiuse.h" @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/src/nrnoc/nrnconfigargs.h.in" + "${PROJECT_BINARY_DIR}/src/nrnoc/nrnconfigargs.h" @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/src/nrncvode/nrnneosm.h.in" + "${PROJECT_BINARY_DIR}/src/nrncvode/nrnneosm.h" @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/src/sundials/sundials_config.h.in" + "${PROJECT_BINARY_DIR}/src/sundials/sundials_config.h" @ONLY) +configure_file("${PROJECT_SOURCE_DIR}/share/lib/nrn.defaults.in" + "${PROJECT_BINARY_DIR}/share/nrn/lib/nrn.defaults" @ONLY) file(COPY ${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib DESTINATION ${PROJECT_BINARY_DIR}/share/nrn/lib) if(NRN_MACOS_BUILD) set(abs_top_builddir ${PROJECT_BINARY_DIR}) - nrn_configure_file(macdist.pkgproj src/mac) - nrn_configure_file(postinstall.sh src/mac) + configure_file("${PROJECT_SOURCE_DIR}/src/mac/macdist.pkgproj.in" + "${PROJECT_BINARY_DIR}/src/mac/macdist.pkgproj" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/src/mac/postinstall.sh.in" + "${PROJECT_BINARY_DIR}/src/mac/postinstall.sh" @ONLY) endif() if(MINGW) dospath("${CMAKE_INSTALL_PREFIX}" WIN_MARSHAL_NRN_DIR) - nrn_configure_file(nrnsetupmingw.nsi src/mswin) - nrn_configure_file(pre_setup_exe.sh src/mswin) + configure_file("${PROJECT_SOURCE_DIR}/src/mswin/nrnsetupmingw.nsi.in" + "${PROJECT_BINARY_DIR}/src/mswin/nrnsetupmingw.nsi" @ONLY) + configure_file("${PROJECT_SOURCE_DIR}/src/mswin/pre_setup_exe.sh.in" + "${PROJECT_BINARY_DIR}/src/mswin/pre_setup_exe.sh" @ONLY) # Just name and not path since setup.exe user chooses location of install. set(CXX x86_64-w64-mingw32-g++.exe) set(BUILD_MINGW_TRUE "") set(BUILD_MINGW_FALSE "#") set(nrnskip_rebase "#") - nrn_configure_file(mknrndll.mak src/mswin/lib) -endif() - -# ============================================================================= -# If Interviews is not provided, configure local files -# ============================================================================= -if(NOT NRN_ENABLE_INTERVIEWS) - nrn_configure_dest_src(config.h . cmake_nrnconf.h .) -else() - file(REMOVE "${PROJECT_BINARY_DIR}/config.h") + configure_file("${PROJECT_SOURCE_DIR}/src/mswin/lib/mknrndll.mak.in" + "${PROJECT_BINARY_DIR}/src/mswin/lib/mknrndll.mak" @ONLY) endif() # Prepare some variables for setup.py extension building (hoc_module, rx3d and music) diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index 482345cacb..df309c19c7 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -79,51 +79,6 @@ macro(nrn_check_signal_return_type VARIABLE) file(REMOVE "conftest.cpp") endmacro() -# ============================================================================= -# Transform PROJECT_SOURCE_DIR/sdir/sfile.in to PROJECT_BINARY_DIR/bdir/bfile -# ============================================================================= -# ~~~ -# This 4 arg macro transformsPROJECT_SOURCE_DIR/sdir/sfile.in into -# PROJECT_BINARY_DIR/bdir/bfile . -# THE shorter two arg form transforms PROJECT_SOURCE_DIR/dir/file.in into -# PROJECT_BINARY_DIR/dir/file -# This first copies with some replacement the sfile.in to _cmake_tmp_bfile.in -# so that the normal cmake configure_file command works to make a proper -# cmake_file. Then that is compared to a possibly existing bfile and, -# if different, copies _cmake_tmp_bfile to bfile. This prevents recompilation of -# .o files that depend on unchanged bfile. The sdir arg is the path relative to -# PROJECT_SOURCE_DIR, the bdir arg is the path relative to PROJECT_BINARY_DIR. -# Note that everytime cmake is run, the bfile is compared to a newly created -# _cmake_tmp_bfile consistent with the current cmake args. -# Note that the sfile arg does NOT contain the .in suffix. -# ~~~ -macro(nrn_configure_dest_src bfile bdir sfile sdir) - set(infile ${PROJECT_SOURCE_DIR}/${sdir}/${sfile}.in) - set(bin_dir ${PROJECT_BINARY_DIR}/${bdir}) - file(MAKE_DIRECTORY ${bin_dir}) - execute_process( - COMMAND sed "s/\#undef *\\(.*\\)/\#cmakedefine \\1 @\\1@/" - INPUT_FILE ${infile} - OUTPUT_FILE ${bin_dir}/_cmake_tmp_${bfile}.in) - configure_file(${bin_dir}/_cmake_tmp_${bfile}.in ${bin_dir}/_cmake_tmp_${bfile} @ONLY) - execute_process(COMMAND cmp -s ${bin_dir}/_cmake_tmp_${bfile} ${bin_dir}/${bfile} - RESULT_VARIABLE result) - if(result EQUAL 0) - file(REMOVE ${bin_dir}/_cmake_tmp_${bfile}) - else() - file(RENAME ${bin_dir}/_cmake_tmp_${bfile} ${bin_dir}/${bfile}) - endif() - file(REMOVE ${bin_dir}/_cmake_tmp_${bfile}.in) - set_property( - DIRECTORY - APPEND - PROPERTY CMAKE_CONFIGURE_DEPENDS ${infile}) -endmacro() - -macro(nrn_configure_file file dir) - nrn_configure_dest_src(${file} ${dir} ${file} ${dir}) -endmacro() - # ============================================================================= # Perform check_include_files and add it to NRN_HEADERS_INCLUDE_LIST if exist Passing an optional # CXX will call check_include_files_cxx instead. diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 58f2b3e5b9..c69a7d0c27 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -1,129 +1,124 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - - -#ifndef H_nrnconf_included -#define H_nrnconf_included 1 - +#pragma once /* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD +#cmakedefine AC_APPLE_UNIVERSAL_BUILD @AC_APPLE_UNIVERSAL_BUILD@ /* if mac os x */ -#undef DARWIN +#cmakedefine DARWIN @DARWIN@ /* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H +#cmakedefine HAVE_DLFCN_H @HAVE_DLFCN_H@ /* Define to 1 if you have the header file. */ -#undef HAVE_EXECINFO_H +#cmakedefine HAVE_EXECINFO_H @HAVE_EXECINFO_H@ /* Define to 1 if you have the `index' function. */ -#undef HAVE_INDEX +#cmakedefine HAVE_INDEX @HAVE_INDEX@ /* Define to 1 if you have the `isatty' function. */ -#undef HAVE_ISATTY +#cmakedefine HAVE_ISATTY @HAVE_ISATTY@ /* define if using InterViews */ -#undef HAVE_IV +#cmakedefine HAVE_IV @HAVE_IV@ /* Define to 1 if you have the `mallinfo' function. */ -#undef HAVE_MALLINFO +#cmakedefine HAVE_MALLINFO @HAVE_MALLINFO@ /* Define to 1 if you have the `mallinfo2' function. */ -#undef HAVE_MALLINFO2 +#cmakedefine HAVE_MALLINFO2 @HAVE_MALLINFO2@ /* Define to 1 if you have the header file. */ -#undef HAVE_MALLOC_H +#cmakedefine HAVE_MALLOC_H @HAVE_MALLOC_H@ /* Define to 1 if you have the `mkstemp' function. */ -#undef HAVE_MKSTEMP +#cmakedefine HAVE_MKSTEMP @HAVE_MKSTEMP@ /* Define to 1 if you have the `posix_memalign' function. */ -#undef HAVE_POSIX_MEMALIGN +#cmakedefine HAVE_POSIX_MEMALIGN @HAVE_POSIX_MEMALIGN@ /* Define to 1 if you have the `setenv' function. */ -#undef HAVE_SETENV +#cmakedefine HAVE_SETENV @HAVE_SETENV@ /* Define to 1 if you have the `setitimer' function. */ -#undef HAVE_SETITIMER +#cmakedefine HAVE_SETITIMER @HAVE_SETITIMER@ /* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION +#cmakedefine HAVE_SIGACTION @HAVE_SIGACTION@ /* Define to 1 if you have the `sigprocmask' function. */ -#undef HAVE_SIGPROCMASK +#cmakedefine HAVE_SIGPROCMASK @HAVE_SIGPROCMASK@ /* (Define if this signal exists) */ -#undef HAVE_SIGBUS +#cmakedefine HAVE_SIGBUS @HAVE_SIGBUS@ /* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H +#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ /* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ /* define if using mingw */ -#undef MINGW +#cmakedefine MINGW @MINGW@ /* where the lib hoc is */ -#undef NEURON_DATA_DIR +#cmakedefine NEURON_DATA_DIR @NEURON_DATA_DIR@ /* host triplet */ -#undef NRNHOST +#cmakedefine NRNHOST @NRNHOST@ /* if 1 then dlopen nrnmech instead of special */ -#undef NRNMECH_DLL_STYLE +#cmakedefine NRNMECH_DLL_STYLE @NRNMECH_DLL_STYLE@ /* if 1 then dynamic units default is legacy units */ -#undef DYNAMIC_UNITS_USE_LEGACY_DEFAULT +#cmakedefine DYNAMIC_UNITS_USE_LEGACY_DEFAULT @DYNAMIC_UNITS_USE_LEGACY_DEFAULT@ /* if nrnoc can use X11 */ -#undef NRNOC_X11 +#cmakedefine NRNOC_X11 @NRNOC_X11@ /* location of NEURON libraries */ -#undef NRN_LIBDIR +#cmakedefine NRN_LIBDIR @NRN_LIBDIR@ /* Name of package */ -#undef PACKAGE +#cmakedefine PACKAGE @PACKAGE@ /* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT +#cmakedefine PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ /* Define to the full name of this package. */ -#undef PACKAGE_NAME +#cmakedefine PACKAGE_NAME @PACKAGE_NAME@ /* Define to the full name and version of this package. */ -#undef PACKAGE_STRING +#cmakedefine PACKAGE_STRING @PACKAGE_STRING@ /* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME +#cmakedefine PACKAGE_TARNAME @PACKAGE_TARNAME@ /* Define to the home page for this package. */ -#undef PACKAGE_URL +#cmakedefine PACKAGE_URL @PACKAGE_URL@ /* Define to the version of this package. */ -#undef PACKAGE_VERSION +#cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ /* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE +#cmakedefine RETSIGTYPE @RETSIGTYPE@ /* define if RETSIGTYPE(*)(int) is not the prototype for a signal handler */ -#undef SIGNAL_CAST +#cmakedefine SIGNAL_CAST @SIGNAL_CAST@ /* Define SUNDIALS data type 'realtype' as 'long double' */ -#undef SUNDIALS_DOUBLE_PRECISION +#cmakedefine SUNDIALS_DOUBLE_PRECISION @SUNDIALS_DOUBLE_PRECISION@ /* Use generic math functions */ -#undef SUNDIALS_USE_GENERIC_MATH +#cmakedefine SUNDIALS_USE_GENERIC_MATH @SUNDIALS_USE_GENERIC_MATH@ /* Define to 1 if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME +#cmakedefine TIME_WITH_SYS_TIME @TIME_WITH_SYS_TIME@ /* Define to 1 if your declares `struct tm'. */ -#undef TM_IN_SYS_TIME +#cmakedefine TM_IN_SYS_TIME @TM_IN_SYS_TIME@ /* Version number of package */ -#undef VERSION +#cmakedefine VERSION @VERSION@ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ @@ -133,29 +128,29 @@ # endif #else # ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN +# cmakedefine WORDS_BIGENDIAN @WORDS_BIGENDIAN@ # endif #endif /* Define to 1 if the X Window System is missing or not being used. */ -#undef X_DISPLAY_MISSING +#cmakedefine X_DISPLAY_MISSING @X_DISPLAY_MISSING@ /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ -#undef YYTEXT_POINTER +#cmakedefine YYTEXT_POINTER @YYTEXT_POINTER@ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ -#undef int64_t +#cmakedefine int64_t @int64_t@ /* Define to `long int' if does not define. */ -#undef off_t +#cmakedefine off_t @off_t@ /* Define to `int' if does not define. */ -#undef pid_t +#cmakedefine pid_t @pid_t@ /* Define to `unsigned int' if does not define. */ -#undef size_t +#cmakedefine size_t @size_t@ /* __cplusplus guard still needed because this header is included from C code in * mesch (and maybe others) @@ -177,5 +172,3 @@ namespace neuron::config { #ifdef MINGW #define WIN32 1 #endif - -#endif /* H_nrnconf_included */ diff --git a/src/nrncvode/nrnneosm.h.in b/src/nrncvode/nrnneosm.h.in index ad61a31526..09e38d1c3a 100755 --- a/src/nrncvode/nrnneosm.h.in +++ b/src/nrncvode/nrnneosm.h.in @@ -1,6 +1,6 @@ /* define to 1 if allowing NEOSIM */ -#undef USENEOSIM +#cmakedefine USENEOSIM @USENEOSIM@ /* define to 1 if allowing NCS */ -#undef USENCS +#cmakedefine USENCS @USENCS@ /* define to 1 (default) if Observer is a base class of DiscreteEvent */ -#undef DISCRETE_EVENT_OBSERVER +#cmakedefine DISCRETE_EVENT_OBSERVER @DISCRETE_EVENT_OBSERVER@ diff --git a/src/oc/nrnmpiuse.h.in b/src/oc/nrnmpiuse.h.in index 4db1c75155..80cf11785b 100755 --- a/src/oc/nrnmpiuse.h.in +++ b/src/oc/nrnmpiuse.h.in @@ -1,19 +1,16 @@ -#ifndef usenrnmpi_h -#define usenrnmpi_h +#pragma once /* define to 1 if you want MPI specific features activated */ -#undef NRNMPI +#cmakedefine NRNMPI @NRNMPI@ /* define to 1 if you want mpi dynamically loaded instead of linked normally */ -#undef NRNMPI_DYNAMICLOAD +#cmakedefine NRNMPI_DYNAMICLOAD @NRNMPI_DYNAMICLOAD@ /* define to 1 if you want the MUSIC - MUlti SImulation Coordinator */ -#undef NRN_MUSIC +#cmakedefine NRN_MUSIC @NRN_MUSIC@ /* define to the dll path if you want to load automatically */ -#undef DLL_DEFAULT_FNAME +#cmakedefine DLL_DEFAULT_FNAME @DLL_DEFAULT_FNAME@ /* define if needed */ -#undef ALWAYS_CALL_MPI_INIT - -#endif +#cmakedefine ALWAYS_CALL_MPI_INIT @ALWAYS_CALL_MPI_INIT@ diff --git a/src/sundials/sundials_config.h.in b/src/sundials/sundials_config.h.in index a043f1ed48..ef6da1b446 100755 --- a/src/sundials/sundials_config.h.in +++ b/src/sundials/sundials_config.h.in @@ -1,70 +1,68 @@ -/* config.hin. Generated from configure.ac by autoheader. */ - /* FCMIX: Define name-mangling macro */ -#undef F77_FUNC +#cmakedefine F77_FUNC @F77_FUNC@ /* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H +#cmakedefine HAVE_DLFCN_H @HAVE_DLFCN_H@ /* Define to 1 if you have the `m' library (-lm). */ -#undef HAVE_LIBM +#cmakedefine HAVE_LIBM @HAVE_LIBM@ /* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ /* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT +#cmakedefine PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ /* Define to the full name of this package. */ -#undef PACKAGE_NAME +#cmakedefine PACKAGE_NAME @PACKAGE_NAME@ /* Define to the full name and version of this package. */ -#undef PACKAGE_STRING +#cmakedefine PACKAGE_STRING @PACKAGE_STRING@ /* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME +#cmakedefine PACKAGE_TARNAME @PACKAGE_TARNAME@ /* Define to the version of this package. */ -#undef PACKAGE_VERSION +#cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ /* The size of a `double', as computed by sizeof. */ -#undef SIZEOF_DOUBLE +#cmakedefine SIZEOF_DOUBLE @SIZEOF_DOUBLE@ /* The size of a `float', as computed by sizeof. */ -#undef SIZEOF_FLOAT +#cmakedefine SIZEOF_FLOAT @SIZEOF_FLOAT@ /* The size of a `int', as computed by sizeof. */ -#undef SIZEOF_INT +#cmakedefine SIZEOF_INT @SIZEOF_INT@ /* The size of a `long double', as computed by sizeof. */ -#undef SIZEOF_LONG_DOUBLE +#cmakedefine SIZEOF_LONG_DOUBLE @SIZEOF_LONG_DOUBLE@ /* The size of a `long int', as computed by sizeof. */ -#undef SIZEOF_LONG_INT +#cmakedefine SIZEOF_LONG_INT @SIZEOF_LONG_INT@ /* FCMIX: Make function names lowercase */ -#undef SUNDIALS_CASE_LOWER +#cmakedefine SUNDIALS_CASE_LOWER @SUNDIALS_CASE_LOWER@ /* FCMIX: Make function names uppercase */ -#undef SUNDIALS_CASE_UPPER +#cmakedefine SUNDIALS_CASE_UPPER @SUNDIALS_CASE_UPPER@ /* Define SUNDIALS data type 'realtype' as 'double' */ -#undef SUNDIALS_DOUBLE_PRECISION +#cmakedefine SUNDIALS_DOUBLE_PRECISION @SUNDIALS_DOUBLE_PRECISION@ /* Define SUNDIALS data type 'realtype' as 'long double' */ -#undef SUNDIALS_EXTENDED_PRECISION +#cmakedefine SUNDIALS_EXTENDED_PRECISION @SUNDIALS_EXTENDED_PRECISION@ /* Define SUNDIALS data type 'realtype' as 'float' */ -#undef SUNDIALS_SINGLE_PRECISION +#cmakedefine SUNDIALS_SINGLE_PRECISION @SUNDIALS_SINGLE_PRECISION@ /* FCMIX: Do NOT append any underscores to functions names */ -#undef SUNDIALS_UNDERSCORE_NONE +#cmakedefine SUNDIALS_UNDERSCORE_NONE @SUNDIALS_UNDERSCORE_NONE@ /* FCMIX: Append ONE underscore to function names */ -#undef SUNDIALS_UNDERSCORE_ONE +#cmakedefine SUNDIALS_UNDERSCORE_ONE @SUNDIALS_UNDERSCORE_ONE@ /* FCMIX: Append TWO underscores to function names */ -#undef SUNDIALS_UNDERSCORE_TWO +#cmakedefine SUNDIALS_UNDERSCORE_TWO @SUNDIALS_UNDERSCORE_TWO@ /* Use generic math functions */ -#undef SUNDIALS_USE_GENERIC_MATH +#cmakedefine SUNDIALS_USE_GENERIC_MATH @SUNDIALS_USE_GENERIC_MATH@ From 84371e0f05b572c04f16c7beded770b9744efc7d Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 24 Apr 2024 20:02:10 +0200 Subject: [PATCH 51/62] Reduce environment variables (#2853) --- cmake/ConfigFileSetting.cmake | 6 --- cmake_nrnconf.h.in | 40 -------------------- src/coreneuron/io/reports/report_handler.cpp | 2 +- src/sundials/sundials_config.h.in | 27 ------------- 4 files changed, 1 insertion(+), 74 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 7243972f37..d456b16d9b 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -1,10 +1,6 @@ # ============================================================================= # Definitions used in nrnconf.h and nmodlconf.h # ============================================================================= -set(PACKAGE_NAME "${PACKAGE}") -set(PACKAGE_TARNAME "${PACKAGE}") -set(PACKAGE_BUGREPORT "\"\"") -set(PACKAGE_URL "\"\"") set(UNQUOTED_PACKAGE_VERSION "${PROJECT_VERSION}") # ~~~ @@ -13,7 +9,6 @@ set(UNQUOTED_PACKAGE_VERSION "${PROJECT_VERSION}") # ~~~ nrn_set_string(PACKAGE "nrn") nrn_set_string(NRNHOST "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}") -nrn_set_string(PACKAGE_STRING "nrn ${PROJECT_VERSION}") nrn_set_string(PACKAGE_VERSION "${PROJECT_VERSION}") nrn_set_string(VERSION "${PROJECT_VERSION}") nrn_set_string(NRN_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib") @@ -24,7 +19,6 @@ nrn_set_string(DLL_DEFAULT_FNAME "${CMAKE_SYSTEM_PROCESSOR}/.libs/libnrnmech.so" add_definitions(-DHAVE_CONFIG_H) set(YYTEXT_POINTER 1) -set(TIME_WITH_SYS_TIME 1) # below two are universal nowadays set(prefix ${CMAKE_INSTALL_PREFIX}) set(host_cpu ${CMAKE_SYSTEM_PROCESSOR}) diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index c69a7d0c27..18bccb7b55 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -69,9 +69,6 @@ /* if 1 then dlopen nrnmech instead of special */ #cmakedefine NRNMECH_DLL_STYLE @NRNMECH_DLL_STYLE@ -/* if 1 then dynamic units default is legacy units */ -#cmakedefine DYNAMIC_UNITS_USE_LEGACY_DEFAULT @DYNAMIC_UNITS_USE_LEGACY_DEFAULT@ - /* if nrnoc can use X11 */ #cmakedefine NRNOC_X11 @NRNOC_X11@ @@ -81,42 +78,18 @@ /* Name of package */ #cmakedefine PACKAGE @PACKAGE@ -/* Define to the address where bug reports for this package should be sent. */ -#cmakedefine PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ - -/* Define to the full name of this package. */ -#cmakedefine PACKAGE_NAME @PACKAGE_NAME@ - -/* Define to the full name and version of this package. */ -#cmakedefine PACKAGE_STRING @PACKAGE_STRING@ - -/* Define to the one symbol short name of this package. */ -#cmakedefine PACKAGE_TARNAME @PACKAGE_TARNAME@ - -/* Define to the home page for this package. */ -#cmakedefine PACKAGE_URL @PACKAGE_URL@ - /* Define to the version of this package. */ #cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ /* Define as the return type of signal handlers (`int' or `void'). */ #cmakedefine RETSIGTYPE @RETSIGTYPE@ -/* define if RETSIGTYPE(*)(int) is not the prototype for a signal handler */ -#cmakedefine SIGNAL_CAST @SIGNAL_CAST@ - /* Define SUNDIALS data type 'realtype' as 'long double' */ #cmakedefine SUNDIALS_DOUBLE_PRECISION @SUNDIALS_DOUBLE_PRECISION@ /* Use generic math functions */ #cmakedefine SUNDIALS_USE_GENERIC_MATH @SUNDIALS_USE_GENERIC_MATH@ -/* Define to 1 if you can safely include both and . */ -#cmakedefine TIME_WITH_SYS_TIME @TIME_WITH_SYS_TIME@ - -/* Define to 1 if your declares `struct tm'. */ -#cmakedefine TM_IN_SYS_TIME @TM_IN_SYS_TIME@ - /* Version number of package */ #cmakedefine VERSION @VERSION@ @@ -132,26 +105,13 @@ # endif #endif -/* Define to 1 if the X Window System is missing or not being used. */ -#cmakedefine X_DISPLAY_MISSING @X_DISPLAY_MISSING@ - /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #cmakedefine YYTEXT_POINTER @YYTEXT_POINTER@ -/* Define to the type of a signed integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#cmakedefine int64_t @int64_t@ - -/* Define to `long int' if does not define. */ -#cmakedefine off_t @off_t@ - /* Define to `int' if does not define. */ #cmakedefine pid_t @pid_t@ -/* Define to `unsigned int' if does not define. */ -#cmakedefine size_t @size_t@ - /* __cplusplus guard still needed because this header is included from C code in * mesch (and maybe others) */ diff --git a/src/coreneuron/io/reports/report_handler.cpp b/src/coreneuron/io/reports/report_handler.cpp index de1cfd64f3..aa01432555 100644 --- a/src/coreneuron/io/reports/report_handler.cpp +++ b/src/coreneuron/io/reports/report_handler.cpp @@ -367,7 +367,7 @@ VarsToReport ReportHandler::get_lfp_vars_to_report(const NrnThread& nt, } auto& summation_report = nt.summation_report_handler_->summation_reports_[report.output_path]; VarsToReport vars_to_report; - off_t offset_lfp = 0; + std::size_t offset_lfp = 0; for (const auto& gid: gids_to_report) { const auto& cell_mapping = mapinfo->get_cell_mapping(gid); if (cell_mapping == nullptr) { diff --git a/src/sundials/sundials_config.h.in b/src/sundials/sundials_config.h.in index ef6da1b446..a378e81360 100755 --- a/src/sundials/sundials_config.h.in +++ b/src/sundials/sundials_config.h.in @@ -10,36 +10,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ -/* Define to the address where bug reports for this package should be sent. */ -#cmakedefine PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ - -/* Define to the full name of this package. */ -#cmakedefine PACKAGE_NAME @PACKAGE_NAME@ - -/* Define to the full name and version of this package. */ -#cmakedefine PACKAGE_STRING @PACKAGE_STRING@ - -/* Define to the one symbol short name of this package. */ -#cmakedefine PACKAGE_TARNAME @PACKAGE_TARNAME@ - /* Define to the version of this package. */ #cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ -/* The size of a `double', as computed by sizeof. */ -#cmakedefine SIZEOF_DOUBLE @SIZEOF_DOUBLE@ - -/* The size of a `float', as computed by sizeof. */ -#cmakedefine SIZEOF_FLOAT @SIZEOF_FLOAT@ - -/* The size of a `int', as computed by sizeof. */ -#cmakedefine SIZEOF_INT @SIZEOF_INT@ - -/* The size of a `long double', as computed by sizeof. */ -#cmakedefine SIZEOF_LONG_DOUBLE @SIZEOF_LONG_DOUBLE@ - -/* The size of a `long int', as computed by sizeof. */ -#cmakedefine SIZEOF_LONG_INT @SIZEOF_LONG_INT@ - /* FCMIX: Make function names lowercase */ #cmakedefine SUNDIALS_CASE_LOWER @SUNDIALS_CASE_LOWER@ From 2dd4518d95def82163d522840b597ccedd7a85d6 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Wed, 24 Apr 2024 16:32:43 -0700 Subject: [PATCH 52/62] windows 11 fix for nrniv -python (#2255) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mingw FILE* incompatible with windows11 Python FILE*. Try to avoid. * Only use gui thread when launched with python. Solves the MINGW crashing and quit problem when launching nrniv and trying to use nrnpython_getline for readline behavior. --------- Co-authored-by: Alexandru Săvulescu --- share/lib/python/neuron/gui.py | 8 ++-- src/nrnpython/nrnpython.cpp | 71 ++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/share/lib/python/neuron/gui.py b/share/lib/python/neuron/gui.py index be3336122d..67d79ac787 100644 --- a/share/lib/python/neuron/gui.py +++ b/share/lib/python/neuron/gui.py @@ -3,6 +3,8 @@ It loads nrngui.hoc, and starts a thread to periodically process the NEURON GUI event loop. + +Note that python threads are not used if nrniv is launched instead of Python """ @@ -105,11 +107,7 @@ def run(self): time.sleep(self.interval) -if ( - h.nrnversion(9) == "2" - or h.nrnversion(8).find("mingw") > 0 - or h.nrnversion(8).find("Windows") -): +if h.nrnversion(9) == "2": # launched with python (instead of nrniv) timer = LoopTimer(0.1, process_events) timer.start() while not timer.started: diff --git a/src/nrnpython/nrnpython.cpp b/src/nrnpython/nrnpython.cpp index 2097630f63..2cd3e7979c 100644 --- a/src/nrnpython/nrnpython.cpp +++ b/src/nrnpython/nrnpython.cpp @@ -16,6 +16,7 @@ #include #include #include +#include extern HocStr* hoc_cbufstr; extern int nrnpy_nositeflag; extern std::string nrnpy_pyexe; @@ -119,16 +120,59 @@ static void nrnpython_set_path(std::string_view fname) { * @return 0 on failure, 1 on success. */ int nrnpy_pyrun(const char* fname) { - nrnpython_set_path(fname); - auto* const fp = fopen(fname, "r"); + auto* fp = fopen(fname, "r"); + if (fp) { + nrnpython_set_path(fname); + } else { + std::cerr << "Could not open " << fname << std::endl; + return 0; + } + fclose(fp); +#if !defined(MINGW) + fp = fopen(fname, "r"); if (fp) { int const code = PyRun_AnyFile(fp, fname); fclose(fp); return !code; - } else { - std::cerr << "Could not open " << fname << std::endl; + } + return 0; +#else // MINGW + // MINGW and Python have incompatible FILE* so try to accomplish + // with pure Python + std::string exec{"with open('"}; + exec += fname; + exec += + "', 'rb') as nrnmingw_file:" + " exec(nrnmingw_file.read(), globals())\n"; + int const code = PyRun_SimpleString(exec.c_str()); + if (code) { + PyErr_Print(); return 0; } + PyRun_SimpleString("del nrnmingw_file\n"); + return 1; +#endif // MINGW +} + +/** + * @brief Like a PyRun_InteractiveLoop that does not need a FILE* + * Use InteractiveConsole to work around the issue of mingw FILE* + * not being compatible with Python via the CAPI on windows11. + * @return 0 on success, nonzero on failure. + */ +static int nrnmingw_pyrun_interactiveloop() { + int code{}; + std::string lines[3]{ + "import code as nrnmingw_code\n", + "nrnmingw_interpreter = nrnmingw_code.InteractiveConsole(locals=globals())\n", + "nrnmingw_interpreter.interact(\"\")\n"}; + for (const auto& line: lines) { + if (PyRun_SimpleString(line.c_str())) { + PyErr_Print(); + return -1; + } + } + return 0; } extern PyObject* nrnpy_hoc(); @@ -265,10 +309,15 @@ static int nrnpython_start(int b) { // There used to be a call to PySys_SetArgv here, which dates back to // e48d933e03b5c25a454e294deea55e399f8ba1b1 and a comment about sys.argv not being set with // nrniv -python. Today, it seems like this is not needed any more. -#if !defined(MINGW) - // cannot get this to avoid crashing with MINGW + + // Used to crash with MINGW when assocated with a python gui thread e.g + // from neuron import h, gui + // g = h.Graph() + // del g + // Also, NEURONMainMenu/File/Quit did not work. The solution to both + // seems to be to just avoid gui threads if MINGW and launched nrniv PyOS_ReadlineFunctionPointer = nrnpython_getline; -#endif + // Is there a -c "command" or file.py arg. bool python_error_encountered{false}, have_reset_sys_path{false}; for (int i = 1; i < nrn_global_argc; ++i) { @@ -299,7 +348,15 @@ static int nrnpython_start(int b) { // it. reset_sys_path(""); } +#if !defined(MINGW) PyRun_InteractiveLoop(hoc_fin, "stdin"); +#else + // mingw FILE incompatible with windows11 Python FILE. + int ret = nrnmingw_pyrun_interactiveloop(); + if (ret) { + python_error_encountered = ret; + } +#endif } return python_error_encountered; } From e4ea94a0b41cb3d6da513fc27ecf50af87bd55e2 Mon Sep 17 00:00:00 2001 From: MikeG Date: Thu, 25 Apr 2024 07:04:00 +0200 Subject: [PATCH 53/62] Fix automake workarounds (#2849) * move src/ivoc/datapath.cpp to src/nrniv/datapath.cpp * move src/ivoc/ocjump.cpp to src/nrniv/ocjump.cpp * don't have src/nrniv/classreg.cpp include src/nrniv/classreg.cpp * Simplify `hoc_class_registration` --- src/ivoc/classreg.cpp | 82 ----- src/ivoc/datapath.cpp | 484 --------------------------- src/ivoc/occlass.h | 25 -- src/ivoc/ocjump.cpp | 159 --------- src/ivoc/symdir.cpp | 572 -------------------------------- src/nrniv/classreg.cpp | 95 +++++- src/nrniv/datapath.cpp | 489 +++++++++++++++++++++++++++- src/{ivoc => nrniv}/datapath.h | 0 src/nrniv/nrnclass.h | 46 --- src/nrniv/ocjump.cpp | 164 +++++++++- src/{ivoc => nrniv}/ocjump.h | 0 src/nrniv/symdir.cpp | 577 ++++++++++++++++++++++++++++++++- src/{ivoc => nrniv}/symdir.h | 0 src/oc/classreg.h | 2 - 14 files changed, 1304 insertions(+), 1391 deletions(-) delete mode 100644 src/ivoc/classreg.cpp delete mode 100644 src/ivoc/datapath.cpp delete mode 100644 src/ivoc/occlass.h delete mode 100644 src/ivoc/ocjump.cpp delete mode 100644 src/ivoc/symdir.cpp mode change 100755 => 100644 src/nrniv/classreg.cpp mode change 100755 => 100644 src/nrniv/datapath.cpp rename src/{ivoc => nrniv}/datapath.h (100%) delete mode 100644 src/nrniv/nrnclass.h mode change 100755 => 100644 src/nrniv/ocjump.cpp rename src/{ivoc => nrniv}/ocjump.h (100%) mode change 100755 => 100644 src/nrniv/symdir.cpp rename src/{ivoc => nrniv}/symdir.h (100%) diff --git a/src/ivoc/classreg.cpp b/src/ivoc/classreg.cpp deleted file mode 100644 index d5e8c81776..0000000000 --- a/src/ivoc/classreg.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include <../../nrnconf.h> -// interface c++ class to oc - -#include -#include -#include "classreg.h" -#ifndef OC_CLASSES -#define OC_CLASSES "occlass.h" -#endif - -#define EXTERNS 1 -extern void -#include OC_CLASSES - ; - -#undef EXTERNS -static void (*register_classes[])() = { -#include OC_CLASSES - , - 0}; - -void hoc_class_registration(void) { - for (int i = 0; register_classes[i]; i++) { - (*register_classes[i])(); - } -} - -/*-----------------------------------------------------*/ -#if 0 -//example - -//the class - -/*static*/ class A { -public: - A(); - ~A(); - void f1(char* s); - double f2(double x); -private: - double x_; -}; - -A::A() { printf("A::A\n"); x_=1; } -A::~A() { printf("A::~A\n"); } -void A::f1(char* s) { printf("A::f1(\"%s\")\n", s);} -double A::f2(double x) { double a = x_; x_=x; return a; } - -//the interface - -static void* A_constructor(Object*) { - printf("A::constructor\n"); - return (void*) new A; -} - -static void A_destructor(void* v) { - delete (A*)v; -} - -static double A_f1(void* v) { - ((A*)v)->f1(gargstr(1)); - return(0.); -} - -static double A_f2(void* v) { - double x = ((A*)v)->f2(*getarg(1)); - return(x); -} - -// class registration to oc - -static Member_func A_member_func[] = { - "f1", A_f1, - "f2", A_f2, - 0, 0 -}; - -void A_reg() { - class2oc("A", A_constructor, A_destructor, A_member_func); -} - -#endif diff --git a/src/ivoc/datapath.cpp b/src/ivoc/datapath.cpp deleted file mode 100644 index c4da677e77..0000000000 --- a/src/ivoc/datapath.cpp +++ /dev/null @@ -1,484 +0,0 @@ -#include <../../nrnconf.h> -#include -#include -#include -#include "hoclist.h" -#if HAVE_IV -#include "graph.h" -#endif -#include "datapath.h" -#include "ivocvect.h" - -#include "nrnoc2iv.h" -#include "membfunc.h" - -#include "parse.hpp" -extern Symlist* hoc_built_in_symlist; -extern Symlist* hoc_top_level_symlist; -extern Objectdata* hoc_top_level_data; - -/*static*/ class PathValue { - public: - PathValue(); - ~PathValue() = default; - std::string path{}; - Symbol* sym; - double original; - char* str; -}; -PathValue::PathValue() { - str = NULL; - sym = NULL; -} - -class HocDataPathImpl { - private: - friend class HocDataPaths; - HocDataPathImpl(int, int); - ~HocDataPathImpl(); - - void search(); - void found(double*, const char*, Symbol*); - void found(char**, const char*, Symbol*); - PathValue* found_v(void*, const char*, Symbol*); - - void search(Objectdata*, Symlist*); - void search_vectors(); - void search_pysec(); - void search(Section*); - void search(Node*, double x); - void search(Point_process*, Symbol*); - void search(Prop*, double x); - - private: - std::map table_; - std::vector strlist_; - int size_, count_, found_so_far_; - int pathstyle_; -}; - -#define sentinal 123456789.e15 - -static Symbol *sym_vec, *sym_v, *sym_vext, *sym_rallbranch, *sym_L, *sym_Ra; - -HocDataPaths::HocDataPaths(int size, int pathstyle) { - if (!sym_vec) { - sym_vec = hoc_table_lookup("Vector", hoc_built_in_symlist); - sym_v = hoc_table_lookup("v", hoc_built_in_symlist); - sym_vext = hoc_table_lookup("vext", hoc_built_in_symlist); - sym_rallbranch = hoc_table_lookup("rallbranch", hoc_built_in_symlist); - sym_L = hoc_table_lookup("L", hoc_built_in_symlist); - sym_Ra = hoc_table_lookup("Ra", hoc_built_in_symlist); - } - impl_ = new HocDataPathImpl(size, pathstyle); -} - -HocDataPaths::~HocDataPaths() { - delete impl_; -} - -int HocDataPaths::style() { - return impl_->pathstyle_; -} - -void HocDataPaths::append(double* pd) { - // printf("HocDataPaths::append\n"); - if (pd && impl_->table_.find((void*) pd) == impl_->table_.end()) { - impl_->table_.emplace((void*) pd, new PathValue); - ++impl_->count_; - } -} - -void HocDataPaths::search() { - // printf("HocDataPaths::search\n"); - impl_->search(); - if (impl_->count_ > impl_->found_so_far_) { - // printf("HocDataPaths:: didn't find paths to all the pointers\n"); - // this has proved to be too often a false alarm since most panels are - // in boxes controlled by objects which have no reference but are - // deleted when the window is closed - } -} - -std::string HocDataPaths::retrieve(double* pd) const { - assert(impl_->pathstyle_ != 2); - // printf("HocDataPaths::retrieve\n"); - auto const it = impl_->table_.find(pd); - if (it != impl_->table_.end()) { - return it->second->path; - } - return {}; -} - -Symbol* HocDataPaths::retrieve_sym(double* pd) const { - // printf("HocDataPaths::retrieve\n"); - auto const it = impl_->table_.find(pd); - if (it != impl_->table_.end()) { - return it->second->sym; - } - return nullptr; -} - -void HocDataPaths::append(char** pd) { - // printf("HocDataPaths::append\n"); - if (*pd && impl_->table_.find((void*) pd) == impl_->table_.end()) { - PathValue* pv = new PathValue; - pv->str = *pd; - impl_->table_.emplace((void*) pd, pv); - ++impl_->count_; - } -} - -std::string HocDataPaths::retrieve(char** pd) const { - // printf("HocDataPaths::retrieve\n"); - auto const it = impl_->table_.find(pd); - if (it != impl_->table_.end()) { - return it->second->path; - } - return {}; -} - -/*------------------------------*/ -HocDataPathImpl::HocDataPathImpl(int size, int pathstyle) { - pathstyle_ = pathstyle; - size_ = size; - count_ = 0; - found_so_far_ = 0; -} - -HocDataPathImpl::~HocDataPathImpl() { - for (auto& kv: table_) { - PathValue* pv = kv.second; - delete pv; - } -} - -void HocDataPathImpl::search() { - found_so_far_ = 0; - for (auto& it: table_) { - PathValue* pv = it.second; - if (pv->str) { - char** pstr = (char**) it.first; - *pstr = nullptr; - } else { - double* pd = (double*) it.first; - pv->original = *pd; - *pd = sentinal; - } - } - if (pathstyle_ > 0) { - search(hoc_top_level_data, hoc_built_in_symlist); - search(hoc_top_level_data, hoc_top_level_symlist); - } else { - search(hoc_top_level_data, hoc_top_level_symlist); - search(hoc_top_level_data, hoc_built_in_symlist); - } - if (found_so_far_ < count_) { - search_pysec(); - } - if (found_so_far_ < count_) { - search_vectors(); - } - for (auto& it: table_) { - PathValue* pv = it.second; - if (pv->str) { - char** pstr = (char**) it.first; - *pstr = pv->str; - } else { - double* pd = (double*) it.first; - *pd = pv->original; - } - } -} - -PathValue* HocDataPathImpl::found_v(void* v, const char* buf, Symbol* sym) { - PathValue* pv; - if (pathstyle_ != 2) { - char path[500]; - std::string cs{}; - for (const auto& str: strlist_) { - Sprintf(path, "%s%s.", cs.c_str(), str.c_str()); - cs = path; - } - Sprintf(path, "%s%s", cs.c_str(), buf); - const auto& it = table_.find(v); - if (it == table_.end()) { - hoc_warning("table lookup failed for pointer for-", path); - return nullptr; - } - pv = it->second; - if (pv->path.empty()) { - pv->path = path; - pv->sym = sym; - ++found_so_far_; - } - // printf("HocDataPathImpl::found %s\n", path); - } else { - const auto& it = table_.find(v); - if (it == table_.end()) { - hoc_warning("table lookup failed for pointer for-", sym->name); - return nullptr; - } - pv = it->second; - if (!pv->sym) { - pv->sym = sym; - ++found_so_far_; - } - } - return pv; -} - -void HocDataPathImpl::found(double* pd, const char* buf, Symbol* sym) { - PathValue* pv = found_v((void*) pd, buf, sym); - if (pv) { - *pd = pv->original; - } -} - -void HocDataPathImpl::found(char** pstr, const char* buf, Symbol* sym) { - PathValue* pv = found_v((void*) pstr, buf, sym); - if (pv) { - *pstr = pv->str; - } else { - hoc_assign_str(pstr, "couldn't find"); - } -} - -void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { - Symbol* sym; - int i, total; - char buf[200]; - std::string cs{}; - if (sl) - for (sym = sl->first; sym; sym = sym->next) { - if (sym->cpublic != 2) { - switch (sym->type) { - case VAR: { - double* pd; - if (sym->subtype == NOTUSER) { - pd = object_pval(sym, od); - total = hoc_total_array_data(sym, od); - } else if (sym->subtype == USERDOUBLE) { - pd = sym->u.pval; - total = 1; - } else { - break; - } - for (i = 0; i < total; ++i) { - if (pd[i] == sentinal) { - Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); - cs = buf; - found(pd + i, cs.c_str(), sym); - } - } - } break; - case STRING: { - char** pstr = object_pstr(sym, od); - if (*pstr == NULL) { - Sprintf(buf, "%s", sym->name); - cs = buf; - found(pstr, cs.c_str(), sym); - } - } break; - case OBJECTVAR: { - if (pathstyle_ > 0) { - break; - } - Object** obp = object_pobj(sym, od); - total = hoc_total_array_data(sym, od); - for (i = 0; i < total; ++i) - if (obp[i] && !obp[i]->recurse) { - cTemplate* t = (obp[i])->ctemplate; - if (!t->constructor) { - // not the this pointer - if (obp[i]->u.dataspace != od) { - Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); - cs = buf; - strlist_.push_back(cs); - obp[i]->recurse = 1; - search(obp[i]->u.dataspace, obp[i]->ctemplate->symtable); - obp[i]->recurse = 0; - strlist_.pop_back(); - } - } else { - /* point processes */ - if (t->is_point_) { - Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); - cs = buf; - strlist_.push_back(cs); - search((Point_process*) obp[i]->u.this_pointer, sym); - strlist_.pop_back(); - } - /* seclists, object lists */ - } - } - } break; - case SECTION: { - total = hoc_total_array_data(sym, od); - for (i = 0; i < total; ++i) { - hoc_Item** pitm = object_psecitm(sym, od); - if (pitm[i]) { - Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); - cs = buf; - strlist_.push_back(cs); - search(hocSEC(pitm[i])); - strlist_.pop_back(); - } - } - } break; - case TEMPLATE: { - cTemplate* t = sym->u.ctemplate; - hoc_Item* q; - ITERATE(q, t->olist) { - Object* obj = OBJ(q); - Sprintf(buf, "%s[%d]", sym->name, obj->index); - cs = buf; - strlist_.push_back(cs); - if (!t->constructor) { - search(obj->u.dataspace, t->symtable); - } else { - if (t->is_point_) { - search((Point_process*) obj->u.this_pointer, sym); - } - } - strlist_.pop_back(); - } - } break; - } - } - } -} - -void HocDataPathImpl::search_vectors() { - char buf[200]; - std::string cs{}; - cTemplate* t = sym_vec->u.ctemplate; - hoc_Item* q; - ITERATE(q, t->olist) { - Object* obj = OBJ(q); - Sprintf(buf, "%s[%d]", sym_vec->name, obj->index); - cs = buf; - strlist_.push_back(cs); - Vect* vec = (Vect*) obj->u.this_pointer; - int size = vec->size(); - double* pd = vector_vec(vec); - for (size_t i = 0; i < size; ++i) { - if (pd[i] == sentinal) { - Sprintf(buf, "x[%zu]", i); - found(pd + i, buf, sym_vec); - } - } - strlist_.pop_back(); - } -} - -void HocDataPathImpl::search_pysec() { -#if USE_PYTHON - std::string cs{}; - hoc_Item* qsec; - // ForAllSections(sec) - ITERATE(qsec, section_list) { - Section* sec = hocSEC(qsec); - if (sec->prop && sec->prop->dparam[PROP_PY_INDEX].get()) { - cs = secname(sec); - strlist_.push_back(cs); - search(sec); - strlist_.pop_back(); - } - } -#endif -} - -void HocDataPathImpl::search(Section* sec) { - if (sec->prop->dparam[2].get() == sentinal) { - found(&(sec->prop->dparam[2].literal_value()), "L", sym_L); - } - if (sec->prop->dparam[4].get() == sentinal) { - found(&(sec->prop->dparam[4].literal_value()), "rallbranch", sym_rallbranch); - } - if (sec->prop->dparam[7].get() == sentinal) { - found(&(sec->prop->dparam[7].literal_value()), "Ra", sym_Ra); - } - if (!sec->parentsec && sec->parentnode) { - search(sec->parentnode, sec->prop->dparam[1].get()); - } - for (int i = 0; i < sec->nnode; ++i) { - search(sec->pnode[i], nrn_arc_position(sec, sec->pnode[i])); - } -} -void HocDataPathImpl::search(Node* nd, double x) { - char buf[100]; - if (NODEV(nd) == sentinal) { - Sprintf(buf, "v(%g)", x); - // the conversion below yields a pointer that is potentially invalidated - // by almost any Node operation - found(static_cast(nd->v_handle()), buf, sym_v); - } - -#if EXTRACELLULAR - if (nd->extnode) { - int i; - for (i = 0; i < nlayer; ++i) { - if (nd->extnode->v[i] == sentinal) { - if (i == 0) { - Sprintf(buf, "vext(%g)", x); - } else { - Sprintf(buf, "vext[%d](%g)", i, x); - } - found(&(nd->extnode->v[i]), buf, sym_vext); - } - } - } -#endif - - Prop* p; - for (p = nd->prop; p; p = p->next) { - if (!memb_func[p->_type].is_point) { - search(p, x); - } - } -} - -void HocDataPathImpl::search(Point_process* pp, Symbol*) { - if (pp->prop) { - search(pp->prop, -1); - } -} - -void HocDataPathImpl::search(Prop* prop, double x) { - char buf[200]; - int type = prop->_type; - Symbol* sym = memb_func[type].sym; - Symbol* psym; - double* pd; - int i, imax, k = 0, ir, kmax = sym->s_varn; - - for (k = 0; k < kmax; ++k) { - psym = sym->u.ppsym[k]; - if (psym->subtype == NRNPOINTER) { - continue; - } - ir = psym->u.rng.index; - if (memb_func[type].hoc_mech) { - pd = prop->ob->u.dataspace[ir].pval; - } else { - if (type == EXTRACELL && ir == neuron::extracellular::vext_pseudoindex()) { - // skip as it was handled by caller - continue; - } else { - pd = static_cast(prop->param_handle_legacy(ir)); - } - } - imax = hoc_total_array_data(psym, 0); - for (i = 0; i < imax; ++i) { - if (pd[i] == sentinal) { - if (x < 0) { - Sprintf(buf, "%s%s", psym->name, hoc_araystr(psym, i, 0)); - } else { - Sprintf(buf, "%s%s(%g)", psym->name, hoc_araystr(psym, i, 0), x); - } - found(pd + i, buf, psym); - } - } - } -} diff --git a/src/ivoc/occlass.h b/src/ivoc/occlass.h deleted file mode 100644 index bd6836ae8d..0000000000 --- a/src/ivoc/occlass.h +++ /dev/null @@ -1,25 +0,0 @@ - -#if EXTERNS -Graph_reg(), HBox_reg(), VBox_reg(), GUIMath_reg(), PWManager_reg(), GrGlyph_reg(), - ValueFieldEditor_reg(), -#if HAVE_IV - TextEditor_reg(), -#endif - OcTimer_reg(), OcDeck_reg(), SymChooser_reg(), StringFunctions_reg(), OcList_reg(), - Vector_reg(), OcPtrVector_reg(), OcFile_reg(), OcPointer_reg(), -#ifdef USEMATRIX - Matrix_reg(), -#endif - Random_reg() -#else -Graph_reg, HBox_reg, VBox_reg, GUIMath_reg, PWManager_reg, GrGlyph_reg, ValueFieldEditor_reg, -#if HAVE_IV - TextEditor_reg, -#endif - OcTimer_reg, OcDeck_reg, SymChooser_reg, StringFunctions_reg, OcList_reg, Vector_reg, - OcPtrVector_reg, OcFile_reg, OcPointer_reg, -#ifdef USEMATRIX - Matrix_reg, -#endif - Random_reg -#endif diff --git a/src/ivoc/ocjump.cpp b/src/ivoc/ocjump.cpp deleted file mode 100644 index 91712f5ec8..0000000000 --- a/src/ivoc/ocjump.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include <../../nrnconf.h> - -#include "nrnfilewrap.h" -#include "nrnoc2iv.h" -#include "ocfunc.h" -#include "ocjump.h" -#if HAVE_IV -#include "ivoc.h" -#endif - -#include - -#include - -extern Objectdata* hoc_top_level_data; -extern Symlist* hoc_top_level_symlist; -extern Symlist* hoc_symlist; -extern Object* hoc_thisobject; -extern int hoc_execerror_messages; - -bool hoc_valid_stmt(const char* stmt, Object* ob) { - std::string s{stmt}; - s.append(1, '\n'); - return OcJump::execute(s.c_str(), ob); -} - -void hoc_execute1() { - Object* ob{}; - int hem{1}; - if (ifarg(2)) { - if (hoc_is_object_arg(2)) { - ob = *hoc_objgetarg(2); - if (ifarg(3)) { - hem = chkarg(3, 0., 1.); - } - } else { - hem = chkarg(2, 0., 1.); - } - } - - auto const hemold = std::exchange(hoc_execerror_messages, hem); - auto const old_mpiabort_flag = std::exchange(nrn_mpiabort_on_error_, 0); - bool const b = hoc_valid_stmt(hoc_gargstr(1), ob); - nrn_mpiabort_on_error_ = old_mpiabort_flag; - hoc_execerror_messages = hemold; - hoc_retpushx(b); -} - -#if HAVE_IV -bool Oc::valid_expr(Symbol* s) { - return OcJump::execute(s->u.u_proc->defn.in); -} - -bool Oc::valid_stmt(const char* stmt, Object* ob) { - return hoc_valid_stmt(stmt, ob); -} -#endif -//------------------------------------------------------------------ -void hoc_execute(Inst*); - -namespace { -struct saved_state { - saved_state() { - // not complete but it is good for expressions and it can be improved - oc_save_hoc_oop(&o1, &o2, &o4, &o5); - oc_save_code(&c1, &c2, c3, &c4, &c5, &c6, &c7, &c8, c9, &c10, &c11, &c12); - oc_save_input_info(&i1, &i2, &i3, &i4); - oc_save_cabcode(&cc1, &cc2); - } - void restore() { - oc_restore_hoc_oop(&o1, &o2, &o4, &o5); - oc_restore_code(&c1, &c2, c3, &c4, &c5, &c6, &c7, &c8, c9, &c10, &c11, &c12); - oc_restore_input_info(i1, i2, i3, i4); - oc_restore_cabcode(&cc1, &cc2); - } - - private: - // hoc_oop - Object* o1{}; - Objectdata* o2{}; - int o4{}; - Symlist* o5{}; - - // code - Inst* c1{}; - Inst* c2{}; - std::size_t c3{}; - nrn::oc::frame* c4{}; - int c5{}; - int c6{}; - Inst* c7{}; - nrn::oc::frame* c8{}; - std::size_t c9{}; - Symlist* c10{}; - Inst* c11{}; - int c12{}; - - // input_info - const char* i1{}; - int i2{}; - int i3{}; - NrnFILEWrap* i4{}; - - // cabcode - int cc1{}; - int cc2{}; -}; -} // namespace - -bool OcJump::execute(Inst* p) { - saved_state before{}; - try_catch_depth_increment tell_children_we_will_catch{}; - try { - hoc_execute(p); - return true; - } catch (...) { - before.restore(); - return false; - } -} - -bool OcJump::execute(const char* stmt, Object* ob) { - saved_state before{}; - try_catch_depth_increment tell_children_we_will_catch{}; - try { - hoc_obj_run(stmt, ob); - return true; - } catch (...) { - before.restore(); - return false; - } -} - -void* OcJump::fpycall(void* (*f)(void*, void*), void* a, void* b) { - saved_state before{}; - try_catch_depth_increment tell_children_we_will_catch{}; - try { - return (*f)(a, b); - } catch (...) { - before.restore(); - throw; - } -} - -ObjectContext::ObjectContext(Object* obj) { - oc_save_hoc_oop(&a1, &a2, &a4, &a5); - hoc_thisobject = obj; - if (obj) { - hoc_objectdata = obj->u.dataspace; - hoc_symlist = obj->ctemplate->symtable; - } else { - hoc_objectdata = hoc_top_level_data; - hoc_symlist = hoc_top_level_symlist; - } -} - -ObjectContext::~ObjectContext() { - oc_restore_hoc_oop(&a1, &a2, &a4, &a5); -} diff --git a/src/ivoc/symdir.cpp b/src/ivoc/symdir.cpp deleted file mode 100644 index 3a2de98cdf..0000000000 --- a/src/ivoc/symdir.cpp +++ /dev/null @@ -1,572 +0,0 @@ -#include <../../nrnconf.h> -#include -#include -#include -#include "ocobserv.h" -#include "utils/enumerate.h" - -#include "nrniv_mf.h" -#include "nrnoc2iv.h" - -#include "membfunc.h" -#include "parse.hpp" -#include "hoclist.h" -extern Symlist* hoc_symlist; -extern Objectdata* hoc_top_level_data; -extern Symlist *hoc_built_in_symlist, *hoc_top_level_symlist; -#include "string.h" -#include "symdir.h" - -#include "nrnsymdiritem.h" - -const char* concat(const char* s1, const char* s2) { - static char* tmp = 0; - int l1 = strlen(s1); - int l2 = strlen(s2); - if (tmp) { - delete[] tmp; - } - tmp = new char[l1 + l2 + 1]; - std::snprintf(tmp, l1 + l2 + 1, "%s%s", s1, s2); - return (const char*) tmp; -} - -class SymDirectoryImpl: public Observer { - public: - void disconnect(Observable*); // watching an object - void update(Observable*); // watching a template - private: - friend class SymDirectory; - Section* sec_; - Object* obj_; - cTemplate* t_; - - std::vector symbol_lists_; - std::string path_; - - void load(int type); - void load(int type, Symlist*); - // void load(Symbol*); - void load_section(); - void load_object(); - void load_aliases(); - void load_template(); - void load_mechanism(const Prop*, int, const char*); - void append(Symbol* sym, Objectdata* od, Object* o = NULL); - void append(Object*); - void un_append(Object*); - void make_pathname(const char*, const char*, const char*, int s = '.'); - void sort(); -}; - -static int compare_entries(const SymbolItem* e1, const SymbolItem* e2) { - int i = strcmp(e1->name().c_str(), e2->name().c_str()); - if (i == 0) { - return e1->array_index() > e2->array_index(); - } - return i > 0; -}; - -void SymDirectoryImpl::sort() { - std::sort(symbol_lists_.begin(), symbol_lists_.end(), compare_entries); -} - -// SymDirectory -SymDirectory::SymDirectory(const std::string& parent_path, - Object* parent_obj, - Symbol* sym, - int array_index, - int) { - impl_ = new SymDirectoryImpl(); - impl_->sec_ = NULL; - impl_->obj_ = NULL; - impl_->t_ = NULL; - Objectdata* obd; - if (parent_obj) { - obd = parent_obj->u.dataspace; - } else { - // obd = hoc_objectdata; - obd = hoc_top_level_data; - } - int suffix = '.'; - if (sym->type == TEMPLATE) { - suffix = '_'; - } - impl_->make_pathname(parent_path.c_str(), - sym->name, - hoc_araystr(sym, array_index, obd), - suffix); - switch (sym->type) { - case SECTION: - if (object_psecitm(sym, obd)[array_index]) { - impl_->sec_ = hocSEC(object_psecitm(sym, obd)[array_index]); - section_ref(impl_->sec_); - impl_->load_section(); - } - break; - case OBJECTVAR: - impl_->obj_ = object_pobj(sym, obd)[array_index]; - if (impl_->obj_) { - ObjObservable::Attach(impl_->obj_, impl_); - impl_->load_object(); - } - break; - case TEMPLATE: - impl_->t_ = sym->u.ctemplate; - ClassObservable::Attach(impl_->t_, impl_); - impl_->load_template(); - break; - case OBJECTALIAS: - impl_->obj_ = sym->u.object_; - if (impl_->obj_) { - ObjObservable::Attach(impl_->obj_, impl_); - impl_->load_object(); - } - break; - default: - hoc_execerror("Don't know how to make a directory out of", path().c_str()); - break; - } - impl_->sort(); -} -SymDirectory::SymDirectory(Object* ob) { - impl_ = new SymDirectoryImpl(); - impl_->sec_ = NULL; - impl_->obj_ = ob; - impl_->t_ = NULL; - int suffix = '.'; - impl_->make_pathname("", hoc_object_name(ob), "", '.'); - ObjObservable::Attach(impl_->obj_, impl_); - impl_->load_object(); - impl_->sort(); -} - -bool SymDirectory::is_pysec(int index) const { - SymbolItem* si = impl_->symbol_lists_.at(index); - return si->pysec_ ? true : false; -} -SymDirectory* SymDirectory::newsymdir(int index) { - SymbolItem* si = impl_->symbol_lists_.at(index); - SymDirectory* d = new SymDirectory(); - if (si->pysec_type_ == PYSECOBJ) { - nrn_symdir_load_pysec(d->impl_->symbol_lists_, si->pysec_); - } else { - d->impl_->sec_ = (Section*) si->pysec_; - section_ref(d->impl_->sec_); - d->impl_->load_section(); - } - d->impl_->path_ = concat(path().c_str(), si->name().c_str()); - d->impl_->path_ = concat(d->impl_->path_.c_str(), "."); - d->impl_->sort(); - return d; -} - -SymDirectory::SymDirectory() { - impl_ = new SymDirectoryImpl(); - impl_->sec_ = NULL; - impl_->obj_ = NULL; - impl_->t_ = NULL; -} - -SymDirectory::SymDirectory(int type) { - ParseTopLevel ptl; - ptl.save(); - impl_ = new SymDirectoryImpl(); - impl_->sec_ = NULL; - impl_->obj_ = NULL; - impl_->t_ = NULL; - impl_->path_ = ""; - impl_->load(type); - impl_->sort(); - ptl.restore(); -} - -SymDirectory::~SymDirectory() { - for (auto& item: impl_->symbol_lists_) { - delete item; - } - impl_->symbol_lists_.clear(); - impl_->symbol_lists_.shrink_to_fit(); - if (impl_->obj_) { - ObjObservable::Detach(impl_->obj_, impl_); - } - if (impl_->t_) { - ClassObservable::Detach(impl_->t_, impl_); - } - if (impl_->sec_) { - section_unref(impl_->sec_); - } - delete impl_; -} -void SymDirectoryImpl::disconnect(Observable*) { - for (auto& item: symbol_lists_) { - delete item; - } - symbol_lists_.clear(); - symbol_lists_.shrink_to_fit(); - obj_ = NULL; -} - -void SymDirectoryImpl::update(Observable* obs) { - if (t_) { // watching a template - ClassObservable* co = (ClassObservable*) obs; - Object* ob = co->object(); - switch (co->message()) { - case ClassObservable::Delete: - un_append(ob); - break; - case ClassObservable::Create: - append(ob); - break; - } - } -} -double* SymDirectory::variable(int index) { - Object* ob = object(); - Symbol* sym = symbol(index); - // printf("::variable index=%d sym=%s ob=%s\n", index, - // sym?sym->name:"SYM0",hoc_object_name(ob)); - if (sym) - switch (sym->type) { - case VAR: - if (ob && ob->ctemplate->constructor) { - extern double* ivoc_vector_ptr(Object*, int); - if (is_obj_type(ob, "Vector")) { - return ivoc_vector_ptr(ob, index); - } else { - return NULL; - } - } else { - Objectdata* od; - if (ob) { - od = ob->u.dataspace; - } else if (sym->subtype == USERDOUBLE) { - return sym->u.pval + array_index(index); - } else { - od = hoc_objectdata; - } - return od[sym->u.oboff].pval + array_index(index); - } - case RANGEVAR: - if (ob && ob->ctemplate->is_point_) { - return static_cast(point_process_pointer( - (Point_process*) ob->u.this_pointer, sym, array_index(index))); - } - break; - } - else { - char buf[256], *cp; - Sprintf(buf, "%s%s", path().c_str(), name(index).c_str()); - if (whole_vector(index)) { // rangevar case for [all] - // replace [all] with [0] - cp = strstr(buf, "[all]"); - assert(cp); - *(++cp) = '0'; - for (++cp; cp[2]; ++cp) { - *cp = cp[2]; - } - *cp = '\0'; - } - return hoc_val_pointer(buf); - } - return NULL; -} - -int SymDirectory::whole_vector(int index) { - return impl_->symbol_lists_.at(index)->whole_vector(); -} - -const std::string& SymDirectory::path() const { - return impl_->path_; -} -int SymDirectory::count() const { - return impl_->symbol_lists_.size(); -} -const std::string& SymDirectory::name(int index) const { - return impl_->symbol_lists_.at(index)->name(); -} -int SymDirectory::array_index(int i) const { - return impl_->symbol_lists_.at(i)->array_index(); -} - -int SymDirectory::index(const std::string& name) const { - for (const auto&& [i, symbol]: enumerate(impl_->symbol_lists_)) { - if (name == symbol->name()) { - return i; - } - } - return -1; -} -void SymDirectory::whole_name(int index, std::string& s) const { - auto s1 = impl_->path_; - auto s2 = name(index); - s = s1 + s2; -} -bool SymDirectory::is_directory(int index) const { - return impl_->symbol_lists_.at(index)->is_directory(); -} -bool SymDirectory::match(const std::string&, const std::string&) { - return true; -} -Symbol* SymDirectory::symbol(int index) const { - return impl_->symbol_lists_.at(index)->symbol(); -} -Object* SymDirectory::object() const { - return impl_->obj_; -} - -Object* SymDirectory::obj(int index) { - return impl_->symbol_lists_.at(index)->object(); -} - -// SymbolItem -SymbolItem::SymbolItem(const char* n, int whole_array) { - symbol_ = NULL; - index_ = 0; - ob_ = NULL; - name_ = n; - whole_array_ = whole_array; - pysec_type_ = 0; - pysec_ = NULL; -} -SymbolItem::SymbolItem(Symbol* sym, Objectdata* od, int index, int whole_array) { - symbol_ = sym; - ob_ = NULL; - whole_array_ = whole_array; - if (ISARRAY(sym)) { - if (whole_array_) { - name_ = concat(sym->name, "[all]"); - } else { - if (od) { - name_ = concat(sym->name, hoc_araystr(sym, index, od)); - } else { - char buf[50]; - Sprintf(buf, "[%d]", index); - name_ = concat(sym->name, buf); - } - } - } else { - name_ = sym->name; - } - index_ = index; - pysec_type_ = 0; - pysec_ = NULL; -} - -int SymbolItem::whole_vector() { - return whole_array_; -} - -SymbolItem::SymbolItem(Object* ob) { - symbol_ = NULL; - index_ = 0; - ob_ = ob; - char buf[10]; - Sprintf(buf, "%d", ob->index); - name_ = buf; - pysec_type_ = 0; - pysec_ = NULL; -} - -void SymbolItem::no_object() { - ob_ = NULL; - name_ = "Deleted"; -} - -SymbolItem::~SymbolItem() {} - -bool SymbolItem::is_directory() const { - if (symbol_) - switch (symbol_->type) { - case SECTION: - case OBJECTVAR: - case TEMPLATE: - case OBJECTALIAS: - // case SECTIONLIST: - // case MECHANISM: - return true; - } - if (ob_) { - return true; - } - if (pysec_) { - return true; - } - return false; -} - -void SymDirectoryImpl::make_pathname(const char* parent, - const char* name, - const char* index, - int suffix) { - char buf[200]; - Sprintf(buf, "%s%s%s%c", parent, name, index, suffix); - path_ = buf; -} - - -void SymDirectoryImpl::load(int type) { - switch (type) { - case TEMPLATE: - load(type, hoc_built_in_symlist); - load(type, hoc_top_level_symlist); - break; - case RANGEVAR: - load(type, hoc_built_in_symlist); - break; - case PYSEC: - path_ = "_pysec."; - nrn_symdir_load_pysec(symbol_lists_, NULL); - break; - default: - load(type, hoc_symlist); - if (hoc_symlist != hoc_built_in_symlist) { - Objectdata* sav = hoc_objectdata; - hoc_objectdata = NULL; - load(type, hoc_built_in_symlist); - hoc_objectdata = sav; - } - if (hoc_symlist != hoc_top_level_symlist) { - load(type, hoc_top_level_symlist); - } - } -} - -void SymDirectoryImpl::load(int type, Symlist* sl) { - for (Symbol* sym = sl->first; sym; sym = sym->next) { - if (type == -1) { - switch (sym->type) { - case SECTION: - case OBJECTVAR: - case VAR: - case TEMPLATE: - append(sym, hoc_objectdata); - } - } else if (sym->type == type) { - append(sym, hoc_objectdata); - } - } -} - -void SymDirectoryImpl::load_object() { - Symlist* sl = obj_->ctemplate->symtable; - Objectdata* od; - if (obj_->ctemplate->constructor) { - od = NULL; - } else { - od = obj_->u.dataspace; - } - if (obj_->aliases) { - load_aliases(); - } - if (sl) - for (Symbol* s = sl->first; s; s = s->next) { - if (s->cpublic) { - append(s, od, obj_); - } - } -} - -void SymDirectoryImpl::load_aliases() { - IvocAliases* a = (IvocAliases*) obj_->aliases; - if (!a) - return; - for (const auto& [_, s]: a->symtab_) { - append(s, nullptr, obj_); - } -} - -void SymDirectoryImpl::load_template() { - hoc_Item* q; - ITERATE(q, t_->olist) { - append(OBJ(q)); - } -} - -void SymDirectoryImpl::load_section() { - char xarg[20]; - char buf[100]; - Section* sec = sec_; - int n = sec->nnode; - - int i = 0; - double x = nrn_arc_position(sec, sec->pnode[0]); - Sprintf(xarg, "( %g )", x); - Sprintf(buf, "v%s", xarg); - symbol_lists_.push_back(new SymbolItem(buf)); - nrn_pushsec(sec); - Node* nd = sec->pnode[i]; - for (const Prop* p = nd->prop; p; p = p->next) { - load_mechanism(p, 0, xarg); - } - nrn_popsec(); -} - -void SymDirectoryImpl::load_mechanism(const Prop* p, int vartype, const char* xarg) { - int type = p->_type; - if (memb_func[type].is_point) { - return; - } - char buf[200]; - Symbol* msym = memb_func[type].sym; - int cnt = msym->s_varn; - for (int i = 0; i < cnt; ++i) { - const Symbol* sym = msym->u.ppsym[i]; - if (nrn_vartype(sym) == vartype || vartype == 0) { - if (ISARRAY(sym)) { - int n = hoc_total_array_data(sym, 0); - if (n > 5) { - Sprintf(buf, "%s[all]%s", sym->name, xarg); - symbol_lists_.push_back(new SymbolItem(buf, n)); - } - Sprintf(buf, "%s[%d]%s", sym->name, 0, xarg); - symbol_lists_.push_back(new SymbolItem(buf)); - Sprintf(buf, "%s[%d]%s", sym->name, n - 1, xarg); - symbol_lists_.push_back(new SymbolItem(buf)); - } else { - Sprintf(buf, "%s%s", sym->name, xarg); - symbol_lists_.push_back(new SymbolItem(buf)); - } - } - } -} - -void SymDirectoryImpl::append(Symbol* sym, Objectdata* od, Object* o) { - if (ISARRAY(sym)) { - int i, n = 1; - if (od) { - n = hoc_total_array_data(sym, od); - } else { // Vector - if (is_obj_type(o, "Vector")) { - extern int ivoc_vector_size(Object*); - n = ivoc_vector_size(o); - } - } - if (n > 5 && sym->type == VAR) { - symbol_lists_.push_back(new SymbolItem(sym, od, 0, n)); - } - for (i = 0; i < n; ++i) { - symbol_lists_.push_back(new SymbolItem(sym, od, i)); - if (i > 5) { - break; - } - } - if (i < n - 1) { - symbol_lists_.push_back(new SymbolItem(sym, od, n - 1)); - } - } else { - symbol_lists_.push_back(new SymbolItem(sym, od, 0)); - } -} - -void SymDirectoryImpl::append(Object* ob) { - symbol_lists_.push_back(new SymbolItem(ob)); -} -void SymDirectoryImpl::un_append(Object* ob) { - for (auto& symbol: symbol_lists_) { - if (symbol->object() == ob) { - symbol->no_object(); - break; - } - } -} diff --git a/src/nrniv/classreg.cpp b/src/nrniv/classreg.cpp old mode 100755 new mode 100644 index cbc150a159..06e27dd5ce --- a/src/nrniv/classreg.cpp +++ b/src/nrniv/classreg.cpp @@ -1,7 +1,90 @@ -/* - * Automake doesn't deal well with source files in a separate directory, so - * this is just a stub to trick it into working right. - */ +#include <../../nrnconf.h> -#define OC_CLASSES "nrnclass.h" -#include "../ivoc/classreg.cpp" +extern void Graph_reg(), HBox_reg(), VBox_reg(), GUIMath_reg(), PWManager_reg(), GrGlyph_reg(), + ValueFieldEditor_reg(), +#if HAVE_IV + TextEditor_reg(), +#endif + OcTimer_reg(), OcDeck_reg(), SymChooser_reg(), StringFunctions_reg(), OcList_reg(), + Vector_reg(), OcPtrVector_reg(), OcFile_reg(), OcPointer_reg(), +#ifdef USEMATRIX + Matrix_reg(), +#endif + Random_reg(), Shape_reg(), PlotShape_reg(), PPShape_reg(), RangeVarPlot_reg(), + SectionBrowser_reg(), MechanismStandard_reg(), MechanismType_reg(), NetCon_reg(), + LinearMechanism_reg(), KSChan_reg(), Impedance_reg(), SaveState_reg(), BBSaveState_reg(), + FInitializeHandler_reg(), StateTransitionEvent_reg(), nrnpython_reg(), +#if USEDASPK + Daspk_reg(), +#endif +#if USECVODE + Cvode_reg(), +#endif +#if USEDSP + DSP_reg(), +#endif +#if USEBBS + ParallelContext_reg(), +#endif + NMODLRandom_reg(); + +void hoc_class_registration(void) { + void (*register_classes[])() = + { Graph_reg, + HBox_reg, + VBox_reg, + GUIMath_reg, + PWManager_reg, + GrGlyph_reg, + ValueFieldEditor_reg, +#if HAVE_IV + TextEditor_reg, +#endif + OcTimer_reg, + OcDeck_reg, + SymChooser_reg, + StringFunctions_reg, + OcList_reg, + Vector_reg, + OcPtrVector_reg, + OcFile_reg, + OcPointer_reg, +#ifdef USEMATRIX + Matrix_reg, +#endif + Random_reg, + Shape_reg, + PlotShape_reg, + PPShape_reg, + RangeVarPlot_reg, + SectionBrowser_reg, + MechanismStandard_reg, + MechanismType_reg, + NetCon_reg, + LinearMechanism_reg, + KSChan_reg, + Impedance_reg, + SaveState_reg, + BBSaveState_reg, + FInitializeHandler_reg, + StateTransitionEvent_reg, + nrnpython_reg, + NMODLRandom_reg, +#if USEDASPK + Daspk_reg, +#endif +#if USECVODE + Cvode_reg, +#endif +#if USEDSP + DSP_reg, +#endif +#if USEBBS + ParallelContext_reg, +#endif + nullptr }; + + for (int i = 0; register_classes[i]; i++) { + (*register_classes[i])(); + } +} diff --git a/src/nrniv/datapath.cpp b/src/nrniv/datapath.cpp old mode 100755 new mode 100644 index 016cc9b124..c4da677e77 --- a/src/nrniv/datapath.cpp +++ b/src/nrniv/datapath.cpp @@ -1,5 +1,484 @@ -/* - * Automake doesn't deal well with source files in a separate directory, so - * this is just a stub to trick it into working right. - */ -#include "../ivoc/datapath.cpp" +#include <../../nrnconf.h> +#include +#include +#include +#include "hoclist.h" +#if HAVE_IV +#include "graph.h" +#endif +#include "datapath.h" +#include "ivocvect.h" + +#include "nrnoc2iv.h" +#include "membfunc.h" + +#include "parse.hpp" +extern Symlist* hoc_built_in_symlist; +extern Symlist* hoc_top_level_symlist; +extern Objectdata* hoc_top_level_data; + +/*static*/ class PathValue { + public: + PathValue(); + ~PathValue() = default; + std::string path{}; + Symbol* sym; + double original; + char* str; +}; +PathValue::PathValue() { + str = NULL; + sym = NULL; +} + +class HocDataPathImpl { + private: + friend class HocDataPaths; + HocDataPathImpl(int, int); + ~HocDataPathImpl(); + + void search(); + void found(double*, const char*, Symbol*); + void found(char**, const char*, Symbol*); + PathValue* found_v(void*, const char*, Symbol*); + + void search(Objectdata*, Symlist*); + void search_vectors(); + void search_pysec(); + void search(Section*); + void search(Node*, double x); + void search(Point_process*, Symbol*); + void search(Prop*, double x); + + private: + std::map table_; + std::vector strlist_; + int size_, count_, found_so_far_; + int pathstyle_; +}; + +#define sentinal 123456789.e15 + +static Symbol *sym_vec, *sym_v, *sym_vext, *sym_rallbranch, *sym_L, *sym_Ra; + +HocDataPaths::HocDataPaths(int size, int pathstyle) { + if (!sym_vec) { + sym_vec = hoc_table_lookup("Vector", hoc_built_in_symlist); + sym_v = hoc_table_lookup("v", hoc_built_in_symlist); + sym_vext = hoc_table_lookup("vext", hoc_built_in_symlist); + sym_rallbranch = hoc_table_lookup("rallbranch", hoc_built_in_symlist); + sym_L = hoc_table_lookup("L", hoc_built_in_symlist); + sym_Ra = hoc_table_lookup("Ra", hoc_built_in_symlist); + } + impl_ = new HocDataPathImpl(size, pathstyle); +} + +HocDataPaths::~HocDataPaths() { + delete impl_; +} + +int HocDataPaths::style() { + return impl_->pathstyle_; +} + +void HocDataPaths::append(double* pd) { + // printf("HocDataPaths::append\n"); + if (pd && impl_->table_.find((void*) pd) == impl_->table_.end()) { + impl_->table_.emplace((void*) pd, new PathValue); + ++impl_->count_; + } +} + +void HocDataPaths::search() { + // printf("HocDataPaths::search\n"); + impl_->search(); + if (impl_->count_ > impl_->found_so_far_) { + // printf("HocDataPaths:: didn't find paths to all the pointers\n"); + // this has proved to be too often a false alarm since most panels are + // in boxes controlled by objects which have no reference but are + // deleted when the window is closed + } +} + +std::string HocDataPaths::retrieve(double* pd) const { + assert(impl_->pathstyle_ != 2); + // printf("HocDataPaths::retrieve\n"); + auto const it = impl_->table_.find(pd); + if (it != impl_->table_.end()) { + return it->second->path; + } + return {}; +} + +Symbol* HocDataPaths::retrieve_sym(double* pd) const { + // printf("HocDataPaths::retrieve\n"); + auto const it = impl_->table_.find(pd); + if (it != impl_->table_.end()) { + return it->second->sym; + } + return nullptr; +} + +void HocDataPaths::append(char** pd) { + // printf("HocDataPaths::append\n"); + if (*pd && impl_->table_.find((void*) pd) == impl_->table_.end()) { + PathValue* pv = new PathValue; + pv->str = *pd; + impl_->table_.emplace((void*) pd, pv); + ++impl_->count_; + } +} + +std::string HocDataPaths::retrieve(char** pd) const { + // printf("HocDataPaths::retrieve\n"); + auto const it = impl_->table_.find(pd); + if (it != impl_->table_.end()) { + return it->second->path; + } + return {}; +} + +/*------------------------------*/ +HocDataPathImpl::HocDataPathImpl(int size, int pathstyle) { + pathstyle_ = pathstyle; + size_ = size; + count_ = 0; + found_so_far_ = 0; +} + +HocDataPathImpl::~HocDataPathImpl() { + for (auto& kv: table_) { + PathValue* pv = kv.second; + delete pv; + } +} + +void HocDataPathImpl::search() { + found_so_far_ = 0; + for (auto& it: table_) { + PathValue* pv = it.second; + if (pv->str) { + char** pstr = (char**) it.first; + *pstr = nullptr; + } else { + double* pd = (double*) it.first; + pv->original = *pd; + *pd = sentinal; + } + } + if (pathstyle_ > 0) { + search(hoc_top_level_data, hoc_built_in_symlist); + search(hoc_top_level_data, hoc_top_level_symlist); + } else { + search(hoc_top_level_data, hoc_top_level_symlist); + search(hoc_top_level_data, hoc_built_in_symlist); + } + if (found_so_far_ < count_) { + search_pysec(); + } + if (found_so_far_ < count_) { + search_vectors(); + } + for (auto& it: table_) { + PathValue* pv = it.second; + if (pv->str) { + char** pstr = (char**) it.first; + *pstr = pv->str; + } else { + double* pd = (double*) it.first; + *pd = pv->original; + } + } +} + +PathValue* HocDataPathImpl::found_v(void* v, const char* buf, Symbol* sym) { + PathValue* pv; + if (pathstyle_ != 2) { + char path[500]; + std::string cs{}; + for (const auto& str: strlist_) { + Sprintf(path, "%s%s.", cs.c_str(), str.c_str()); + cs = path; + } + Sprintf(path, "%s%s", cs.c_str(), buf); + const auto& it = table_.find(v); + if (it == table_.end()) { + hoc_warning("table lookup failed for pointer for-", path); + return nullptr; + } + pv = it->second; + if (pv->path.empty()) { + pv->path = path; + pv->sym = sym; + ++found_so_far_; + } + // printf("HocDataPathImpl::found %s\n", path); + } else { + const auto& it = table_.find(v); + if (it == table_.end()) { + hoc_warning("table lookup failed for pointer for-", sym->name); + return nullptr; + } + pv = it->second; + if (!pv->sym) { + pv->sym = sym; + ++found_so_far_; + } + } + return pv; +} + +void HocDataPathImpl::found(double* pd, const char* buf, Symbol* sym) { + PathValue* pv = found_v((void*) pd, buf, sym); + if (pv) { + *pd = pv->original; + } +} + +void HocDataPathImpl::found(char** pstr, const char* buf, Symbol* sym) { + PathValue* pv = found_v((void*) pstr, buf, sym); + if (pv) { + *pstr = pv->str; + } else { + hoc_assign_str(pstr, "couldn't find"); + } +} + +void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { + Symbol* sym; + int i, total; + char buf[200]; + std::string cs{}; + if (sl) + for (sym = sl->first; sym; sym = sym->next) { + if (sym->cpublic != 2) { + switch (sym->type) { + case VAR: { + double* pd; + if (sym->subtype == NOTUSER) { + pd = object_pval(sym, od); + total = hoc_total_array_data(sym, od); + } else if (sym->subtype == USERDOUBLE) { + pd = sym->u.pval; + total = 1; + } else { + break; + } + for (i = 0; i < total; ++i) { + if (pd[i] == sentinal) { + Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); + cs = buf; + found(pd + i, cs.c_str(), sym); + } + } + } break; + case STRING: { + char** pstr = object_pstr(sym, od); + if (*pstr == NULL) { + Sprintf(buf, "%s", sym->name); + cs = buf; + found(pstr, cs.c_str(), sym); + } + } break; + case OBJECTVAR: { + if (pathstyle_ > 0) { + break; + } + Object** obp = object_pobj(sym, od); + total = hoc_total_array_data(sym, od); + for (i = 0; i < total; ++i) + if (obp[i] && !obp[i]->recurse) { + cTemplate* t = (obp[i])->ctemplate; + if (!t->constructor) { + // not the this pointer + if (obp[i]->u.dataspace != od) { + Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); + cs = buf; + strlist_.push_back(cs); + obp[i]->recurse = 1; + search(obp[i]->u.dataspace, obp[i]->ctemplate->symtable); + obp[i]->recurse = 0; + strlist_.pop_back(); + } + } else { + /* point processes */ + if (t->is_point_) { + Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); + cs = buf; + strlist_.push_back(cs); + search((Point_process*) obp[i]->u.this_pointer, sym); + strlist_.pop_back(); + } + /* seclists, object lists */ + } + } + } break; + case SECTION: { + total = hoc_total_array_data(sym, od); + for (i = 0; i < total; ++i) { + hoc_Item** pitm = object_psecitm(sym, od); + if (pitm[i]) { + Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); + cs = buf; + strlist_.push_back(cs); + search(hocSEC(pitm[i])); + strlist_.pop_back(); + } + } + } break; + case TEMPLATE: { + cTemplate* t = sym->u.ctemplate; + hoc_Item* q; + ITERATE(q, t->olist) { + Object* obj = OBJ(q); + Sprintf(buf, "%s[%d]", sym->name, obj->index); + cs = buf; + strlist_.push_back(cs); + if (!t->constructor) { + search(obj->u.dataspace, t->symtable); + } else { + if (t->is_point_) { + search((Point_process*) obj->u.this_pointer, sym); + } + } + strlist_.pop_back(); + } + } break; + } + } + } +} + +void HocDataPathImpl::search_vectors() { + char buf[200]; + std::string cs{}; + cTemplate* t = sym_vec->u.ctemplate; + hoc_Item* q; + ITERATE(q, t->olist) { + Object* obj = OBJ(q); + Sprintf(buf, "%s[%d]", sym_vec->name, obj->index); + cs = buf; + strlist_.push_back(cs); + Vect* vec = (Vect*) obj->u.this_pointer; + int size = vec->size(); + double* pd = vector_vec(vec); + for (size_t i = 0; i < size; ++i) { + if (pd[i] == sentinal) { + Sprintf(buf, "x[%zu]", i); + found(pd + i, buf, sym_vec); + } + } + strlist_.pop_back(); + } +} + +void HocDataPathImpl::search_pysec() { +#if USE_PYTHON + std::string cs{}; + hoc_Item* qsec; + // ForAllSections(sec) + ITERATE(qsec, section_list) { + Section* sec = hocSEC(qsec); + if (sec->prop && sec->prop->dparam[PROP_PY_INDEX].get()) { + cs = secname(sec); + strlist_.push_back(cs); + search(sec); + strlist_.pop_back(); + } + } +#endif +} + +void HocDataPathImpl::search(Section* sec) { + if (sec->prop->dparam[2].get() == sentinal) { + found(&(sec->prop->dparam[2].literal_value()), "L", sym_L); + } + if (sec->prop->dparam[4].get() == sentinal) { + found(&(sec->prop->dparam[4].literal_value()), "rallbranch", sym_rallbranch); + } + if (sec->prop->dparam[7].get() == sentinal) { + found(&(sec->prop->dparam[7].literal_value()), "Ra", sym_Ra); + } + if (!sec->parentsec && sec->parentnode) { + search(sec->parentnode, sec->prop->dparam[1].get()); + } + for (int i = 0; i < sec->nnode; ++i) { + search(sec->pnode[i], nrn_arc_position(sec, sec->pnode[i])); + } +} +void HocDataPathImpl::search(Node* nd, double x) { + char buf[100]; + if (NODEV(nd) == sentinal) { + Sprintf(buf, "v(%g)", x); + // the conversion below yields a pointer that is potentially invalidated + // by almost any Node operation + found(static_cast(nd->v_handle()), buf, sym_v); + } + +#if EXTRACELLULAR + if (nd->extnode) { + int i; + for (i = 0; i < nlayer; ++i) { + if (nd->extnode->v[i] == sentinal) { + if (i == 0) { + Sprintf(buf, "vext(%g)", x); + } else { + Sprintf(buf, "vext[%d](%g)", i, x); + } + found(&(nd->extnode->v[i]), buf, sym_vext); + } + } + } +#endif + + Prop* p; + for (p = nd->prop; p; p = p->next) { + if (!memb_func[p->_type].is_point) { + search(p, x); + } + } +} + +void HocDataPathImpl::search(Point_process* pp, Symbol*) { + if (pp->prop) { + search(pp->prop, -1); + } +} + +void HocDataPathImpl::search(Prop* prop, double x) { + char buf[200]; + int type = prop->_type; + Symbol* sym = memb_func[type].sym; + Symbol* psym; + double* pd; + int i, imax, k = 0, ir, kmax = sym->s_varn; + + for (k = 0; k < kmax; ++k) { + psym = sym->u.ppsym[k]; + if (psym->subtype == NRNPOINTER) { + continue; + } + ir = psym->u.rng.index; + if (memb_func[type].hoc_mech) { + pd = prop->ob->u.dataspace[ir].pval; + } else { + if (type == EXTRACELL && ir == neuron::extracellular::vext_pseudoindex()) { + // skip as it was handled by caller + continue; + } else { + pd = static_cast(prop->param_handle_legacy(ir)); + } + } + imax = hoc_total_array_data(psym, 0); + for (i = 0; i < imax; ++i) { + if (pd[i] == sentinal) { + if (x < 0) { + Sprintf(buf, "%s%s", psym->name, hoc_araystr(psym, i, 0)); + } else { + Sprintf(buf, "%s%s(%g)", psym->name, hoc_araystr(psym, i, 0), x); + } + found(pd + i, buf, psym); + } + } + } +} diff --git a/src/ivoc/datapath.h b/src/nrniv/datapath.h similarity index 100% rename from src/ivoc/datapath.h rename to src/nrniv/datapath.h diff --git a/src/nrniv/nrnclass.h b/src/nrniv/nrnclass.h deleted file mode 100644 index dcc42b1120..0000000000 --- a/src/nrniv/nrnclass.h +++ /dev/null @@ -1,46 +0,0 @@ -#include "occlass.h" -#if EXTERNS -, Shape_reg(), PlotShape_reg(), PPShape_reg(), RangeVarPlot_reg(), SectionBrowser_reg(), - MechanismStandard_reg(), MechanismType_reg(), NetCon_reg(), LinearMechanism_reg(), KSChan_reg(), - Impedance_reg(), SaveState_reg(), BBSaveState_reg(), FInitializeHandler_reg(), - StateTransitionEvent_reg(), nrnpython_reg(), NMODLRandom_reg() -#if USEDASPK - , - Daspk_reg() -#endif -#if USECVODE - , - Cvode_reg() -#endif -#if USEDSP - , - DSP_reg() -#endif -#if USEBBS - , - ParallelContext_reg() -#endif - -#else // EXTERNS - -, Shape_reg, PlotShape_reg, PPShape_reg, RangeVarPlot_reg, SectionBrowser_reg, - MechanismStandard_reg, MechanismType_reg, NetCon_reg, LinearMechanism_reg, KSChan_reg, - Impedance_reg, SaveState_reg, BBSaveState_reg, FInitializeHandler_reg, StateTransitionEvent_reg, - nrnpython_reg, NMODLRandom_reg -#if USEDASPK - , - Daspk_reg -#endif -#if USECVODE - , - Cvode_reg -#endif -#if USEDSP - , - DSP_reg -#endif -#if USEBBS - , - ParallelContext_reg -#endif -#endif // !EXTERNS diff --git a/src/nrniv/ocjump.cpp b/src/nrniv/ocjump.cpp old mode 100755 new mode 100644 index 262bc50604..91712f5ec8 --- a/src/nrniv/ocjump.cpp +++ b/src/nrniv/ocjump.cpp @@ -1,5 +1,159 @@ -/* - * Automake doesn't deal well with source files in a separate directory, so - * this is just a stub to trick it into working right. - */ -#include "../ivoc/ocjump.cpp" +#include <../../nrnconf.h> + +#include "nrnfilewrap.h" +#include "nrnoc2iv.h" +#include "ocfunc.h" +#include "ocjump.h" +#if HAVE_IV +#include "ivoc.h" +#endif + +#include + +#include + +extern Objectdata* hoc_top_level_data; +extern Symlist* hoc_top_level_symlist; +extern Symlist* hoc_symlist; +extern Object* hoc_thisobject; +extern int hoc_execerror_messages; + +bool hoc_valid_stmt(const char* stmt, Object* ob) { + std::string s{stmt}; + s.append(1, '\n'); + return OcJump::execute(s.c_str(), ob); +} + +void hoc_execute1() { + Object* ob{}; + int hem{1}; + if (ifarg(2)) { + if (hoc_is_object_arg(2)) { + ob = *hoc_objgetarg(2); + if (ifarg(3)) { + hem = chkarg(3, 0., 1.); + } + } else { + hem = chkarg(2, 0., 1.); + } + } + + auto const hemold = std::exchange(hoc_execerror_messages, hem); + auto const old_mpiabort_flag = std::exchange(nrn_mpiabort_on_error_, 0); + bool const b = hoc_valid_stmt(hoc_gargstr(1), ob); + nrn_mpiabort_on_error_ = old_mpiabort_flag; + hoc_execerror_messages = hemold; + hoc_retpushx(b); +} + +#if HAVE_IV +bool Oc::valid_expr(Symbol* s) { + return OcJump::execute(s->u.u_proc->defn.in); +} + +bool Oc::valid_stmt(const char* stmt, Object* ob) { + return hoc_valid_stmt(stmt, ob); +} +#endif +//------------------------------------------------------------------ +void hoc_execute(Inst*); + +namespace { +struct saved_state { + saved_state() { + // not complete but it is good for expressions and it can be improved + oc_save_hoc_oop(&o1, &o2, &o4, &o5); + oc_save_code(&c1, &c2, c3, &c4, &c5, &c6, &c7, &c8, c9, &c10, &c11, &c12); + oc_save_input_info(&i1, &i2, &i3, &i4); + oc_save_cabcode(&cc1, &cc2); + } + void restore() { + oc_restore_hoc_oop(&o1, &o2, &o4, &o5); + oc_restore_code(&c1, &c2, c3, &c4, &c5, &c6, &c7, &c8, c9, &c10, &c11, &c12); + oc_restore_input_info(i1, i2, i3, i4); + oc_restore_cabcode(&cc1, &cc2); + } + + private: + // hoc_oop + Object* o1{}; + Objectdata* o2{}; + int o4{}; + Symlist* o5{}; + + // code + Inst* c1{}; + Inst* c2{}; + std::size_t c3{}; + nrn::oc::frame* c4{}; + int c5{}; + int c6{}; + Inst* c7{}; + nrn::oc::frame* c8{}; + std::size_t c9{}; + Symlist* c10{}; + Inst* c11{}; + int c12{}; + + // input_info + const char* i1{}; + int i2{}; + int i3{}; + NrnFILEWrap* i4{}; + + // cabcode + int cc1{}; + int cc2{}; +}; +} // namespace + +bool OcJump::execute(Inst* p) { + saved_state before{}; + try_catch_depth_increment tell_children_we_will_catch{}; + try { + hoc_execute(p); + return true; + } catch (...) { + before.restore(); + return false; + } +} + +bool OcJump::execute(const char* stmt, Object* ob) { + saved_state before{}; + try_catch_depth_increment tell_children_we_will_catch{}; + try { + hoc_obj_run(stmt, ob); + return true; + } catch (...) { + before.restore(); + return false; + } +} + +void* OcJump::fpycall(void* (*f)(void*, void*), void* a, void* b) { + saved_state before{}; + try_catch_depth_increment tell_children_we_will_catch{}; + try { + return (*f)(a, b); + } catch (...) { + before.restore(); + throw; + } +} + +ObjectContext::ObjectContext(Object* obj) { + oc_save_hoc_oop(&a1, &a2, &a4, &a5); + hoc_thisobject = obj; + if (obj) { + hoc_objectdata = obj->u.dataspace; + hoc_symlist = obj->ctemplate->symtable; + } else { + hoc_objectdata = hoc_top_level_data; + hoc_symlist = hoc_top_level_symlist; + } +} + +ObjectContext::~ObjectContext() { + oc_restore_hoc_oop(&a1, &a2, &a4, &a5); +} diff --git a/src/ivoc/ocjump.h b/src/nrniv/ocjump.h similarity index 100% rename from src/ivoc/ocjump.h rename to src/nrniv/ocjump.h diff --git a/src/nrniv/symdir.cpp b/src/nrniv/symdir.cpp old mode 100755 new mode 100644 index eee5dfcad0..3a2de98cdf --- a/src/nrniv/symdir.cpp +++ b/src/nrniv/symdir.cpp @@ -1,5 +1,572 @@ -/* - * Automake doesn't deal well with source files in a separate directory, so - * this is just a stub to trick it into working right. - */ -#include "../ivoc/symdir.cpp" +#include <../../nrnconf.h> +#include +#include +#include +#include "ocobserv.h" +#include "utils/enumerate.h" + +#include "nrniv_mf.h" +#include "nrnoc2iv.h" + +#include "membfunc.h" +#include "parse.hpp" +#include "hoclist.h" +extern Symlist* hoc_symlist; +extern Objectdata* hoc_top_level_data; +extern Symlist *hoc_built_in_symlist, *hoc_top_level_symlist; +#include "string.h" +#include "symdir.h" + +#include "nrnsymdiritem.h" + +const char* concat(const char* s1, const char* s2) { + static char* tmp = 0; + int l1 = strlen(s1); + int l2 = strlen(s2); + if (tmp) { + delete[] tmp; + } + tmp = new char[l1 + l2 + 1]; + std::snprintf(tmp, l1 + l2 + 1, "%s%s", s1, s2); + return (const char*) tmp; +} + +class SymDirectoryImpl: public Observer { + public: + void disconnect(Observable*); // watching an object + void update(Observable*); // watching a template + private: + friend class SymDirectory; + Section* sec_; + Object* obj_; + cTemplate* t_; + + std::vector symbol_lists_; + std::string path_; + + void load(int type); + void load(int type, Symlist*); + // void load(Symbol*); + void load_section(); + void load_object(); + void load_aliases(); + void load_template(); + void load_mechanism(const Prop*, int, const char*); + void append(Symbol* sym, Objectdata* od, Object* o = NULL); + void append(Object*); + void un_append(Object*); + void make_pathname(const char*, const char*, const char*, int s = '.'); + void sort(); +}; + +static int compare_entries(const SymbolItem* e1, const SymbolItem* e2) { + int i = strcmp(e1->name().c_str(), e2->name().c_str()); + if (i == 0) { + return e1->array_index() > e2->array_index(); + } + return i > 0; +}; + +void SymDirectoryImpl::sort() { + std::sort(symbol_lists_.begin(), symbol_lists_.end(), compare_entries); +} + +// SymDirectory +SymDirectory::SymDirectory(const std::string& parent_path, + Object* parent_obj, + Symbol* sym, + int array_index, + int) { + impl_ = new SymDirectoryImpl(); + impl_->sec_ = NULL; + impl_->obj_ = NULL; + impl_->t_ = NULL; + Objectdata* obd; + if (parent_obj) { + obd = parent_obj->u.dataspace; + } else { + // obd = hoc_objectdata; + obd = hoc_top_level_data; + } + int suffix = '.'; + if (sym->type == TEMPLATE) { + suffix = '_'; + } + impl_->make_pathname(parent_path.c_str(), + sym->name, + hoc_araystr(sym, array_index, obd), + suffix); + switch (sym->type) { + case SECTION: + if (object_psecitm(sym, obd)[array_index]) { + impl_->sec_ = hocSEC(object_psecitm(sym, obd)[array_index]); + section_ref(impl_->sec_); + impl_->load_section(); + } + break; + case OBJECTVAR: + impl_->obj_ = object_pobj(sym, obd)[array_index]; + if (impl_->obj_) { + ObjObservable::Attach(impl_->obj_, impl_); + impl_->load_object(); + } + break; + case TEMPLATE: + impl_->t_ = sym->u.ctemplate; + ClassObservable::Attach(impl_->t_, impl_); + impl_->load_template(); + break; + case OBJECTALIAS: + impl_->obj_ = sym->u.object_; + if (impl_->obj_) { + ObjObservable::Attach(impl_->obj_, impl_); + impl_->load_object(); + } + break; + default: + hoc_execerror("Don't know how to make a directory out of", path().c_str()); + break; + } + impl_->sort(); +} +SymDirectory::SymDirectory(Object* ob) { + impl_ = new SymDirectoryImpl(); + impl_->sec_ = NULL; + impl_->obj_ = ob; + impl_->t_ = NULL; + int suffix = '.'; + impl_->make_pathname("", hoc_object_name(ob), "", '.'); + ObjObservable::Attach(impl_->obj_, impl_); + impl_->load_object(); + impl_->sort(); +} + +bool SymDirectory::is_pysec(int index) const { + SymbolItem* si = impl_->symbol_lists_.at(index); + return si->pysec_ ? true : false; +} +SymDirectory* SymDirectory::newsymdir(int index) { + SymbolItem* si = impl_->symbol_lists_.at(index); + SymDirectory* d = new SymDirectory(); + if (si->pysec_type_ == PYSECOBJ) { + nrn_symdir_load_pysec(d->impl_->symbol_lists_, si->pysec_); + } else { + d->impl_->sec_ = (Section*) si->pysec_; + section_ref(d->impl_->sec_); + d->impl_->load_section(); + } + d->impl_->path_ = concat(path().c_str(), si->name().c_str()); + d->impl_->path_ = concat(d->impl_->path_.c_str(), "."); + d->impl_->sort(); + return d; +} + +SymDirectory::SymDirectory() { + impl_ = new SymDirectoryImpl(); + impl_->sec_ = NULL; + impl_->obj_ = NULL; + impl_->t_ = NULL; +} + +SymDirectory::SymDirectory(int type) { + ParseTopLevel ptl; + ptl.save(); + impl_ = new SymDirectoryImpl(); + impl_->sec_ = NULL; + impl_->obj_ = NULL; + impl_->t_ = NULL; + impl_->path_ = ""; + impl_->load(type); + impl_->sort(); + ptl.restore(); +} + +SymDirectory::~SymDirectory() { + for (auto& item: impl_->symbol_lists_) { + delete item; + } + impl_->symbol_lists_.clear(); + impl_->symbol_lists_.shrink_to_fit(); + if (impl_->obj_) { + ObjObservable::Detach(impl_->obj_, impl_); + } + if (impl_->t_) { + ClassObservable::Detach(impl_->t_, impl_); + } + if (impl_->sec_) { + section_unref(impl_->sec_); + } + delete impl_; +} +void SymDirectoryImpl::disconnect(Observable*) { + for (auto& item: symbol_lists_) { + delete item; + } + symbol_lists_.clear(); + symbol_lists_.shrink_to_fit(); + obj_ = NULL; +} + +void SymDirectoryImpl::update(Observable* obs) { + if (t_) { // watching a template + ClassObservable* co = (ClassObservable*) obs; + Object* ob = co->object(); + switch (co->message()) { + case ClassObservable::Delete: + un_append(ob); + break; + case ClassObservable::Create: + append(ob); + break; + } + } +} +double* SymDirectory::variable(int index) { + Object* ob = object(); + Symbol* sym = symbol(index); + // printf("::variable index=%d sym=%s ob=%s\n", index, + // sym?sym->name:"SYM0",hoc_object_name(ob)); + if (sym) + switch (sym->type) { + case VAR: + if (ob && ob->ctemplate->constructor) { + extern double* ivoc_vector_ptr(Object*, int); + if (is_obj_type(ob, "Vector")) { + return ivoc_vector_ptr(ob, index); + } else { + return NULL; + } + } else { + Objectdata* od; + if (ob) { + od = ob->u.dataspace; + } else if (sym->subtype == USERDOUBLE) { + return sym->u.pval + array_index(index); + } else { + od = hoc_objectdata; + } + return od[sym->u.oboff].pval + array_index(index); + } + case RANGEVAR: + if (ob && ob->ctemplate->is_point_) { + return static_cast(point_process_pointer( + (Point_process*) ob->u.this_pointer, sym, array_index(index))); + } + break; + } + else { + char buf[256], *cp; + Sprintf(buf, "%s%s", path().c_str(), name(index).c_str()); + if (whole_vector(index)) { // rangevar case for [all] + // replace [all] with [0] + cp = strstr(buf, "[all]"); + assert(cp); + *(++cp) = '0'; + for (++cp; cp[2]; ++cp) { + *cp = cp[2]; + } + *cp = '\0'; + } + return hoc_val_pointer(buf); + } + return NULL; +} + +int SymDirectory::whole_vector(int index) { + return impl_->symbol_lists_.at(index)->whole_vector(); +} + +const std::string& SymDirectory::path() const { + return impl_->path_; +} +int SymDirectory::count() const { + return impl_->symbol_lists_.size(); +} +const std::string& SymDirectory::name(int index) const { + return impl_->symbol_lists_.at(index)->name(); +} +int SymDirectory::array_index(int i) const { + return impl_->symbol_lists_.at(i)->array_index(); +} + +int SymDirectory::index(const std::string& name) const { + for (const auto&& [i, symbol]: enumerate(impl_->symbol_lists_)) { + if (name == symbol->name()) { + return i; + } + } + return -1; +} +void SymDirectory::whole_name(int index, std::string& s) const { + auto s1 = impl_->path_; + auto s2 = name(index); + s = s1 + s2; +} +bool SymDirectory::is_directory(int index) const { + return impl_->symbol_lists_.at(index)->is_directory(); +} +bool SymDirectory::match(const std::string&, const std::string&) { + return true; +} +Symbol* SymDirectory::symbol(int index) const { + return impl_->symbol_lists_.at(index)->symbol(); +} +Object* SymDirectory::object() const { + return impl_->obj_; +} + +Object* SymDirectory::obj(int index) { + return impl_->symbol_lists_.at(index)->object(); +} + +// SymbolItem +SymbolItem::SymbolItem(const char* n, int whole_array) { + symbol_ = NULL; + index_ = 0; + ob_ = NULL; + name_ = n; + whole_array_ = whole_array; + pysec_type_ = 0; + pysec_ = NULL; +} +SymbolItem::SymbolItem(Symbol* sym, Objectdata* od, int index, int whole_array) { + symbol_ = sym; + ob_ = NULL; + whole_array_ = whole_array; + if (ISARRAY(sym)) { + if (whole_array_) { + name_ = concat(sym->name, "[all]"); + } else { + if (od) { + name_ = concat(sym->name, hoc_araystr(sym, index, od)); + } else { + char buf[50]; + Sprintf(buf, "[%d]", index); + name_ = concat(sym->name, buf); + } + } + } else { + name_ = sym->name; + } + index_ = index; + pysec_type_ = 0; + pysec_ = NULL; +} + +int SymbolItem::whole_vector() { + return whole_array_; +} + +SymbolItem::SymbolItem(Object* ob) { + symbol_ = NULL; + index_ = 0; + ob_ = ob; + char buf[10]; + Sprintf(buf, "%d", ob->index); + name_ = buf; + pysec_type_ = 0; + pysec_ = NULL; +} + +void SymbolItem::no_object() { + ob_ = NULL; + name_ = "Deleted"; +} + +SymbolItem::~SymbolItem() {} + +bool SymbolItem::is_directory() const { + if (symbol_) + switch (symbol_->type) { + case SECTION: + case OBJECTVAR: + case TEMPLATE: + case OBJECTALIAS: + // case SECTIONLIST: + // case MECHANISM: + return true; + } + if (ob_) { + return true; + } + if (pysec_) { + return true; + } + return false; +} + +void SymDirectoryImpl::make_pathname(const char* parent, + const char* name, + const char* index, + int suffix) { + char buf[200]; + Sprintf(buf, "%s%s%s%c", parent, name, index, suffix); + path_ = buf; +} + + +void SymDirectoryImpl::load(int type) { + switch (type) { + case TEMPLATE: + load(type, hoc_built_in_symlist); + load(type, hoc_top_level_symlist); + break; + case RANGEVAR: + load(type, hoc_built_in_symlist); + break; + case PYSEC: + path_ = "_pysec."; + nrn_symdir_load_pysec(symbol_lists_, NULL); + break; + default: + load(type, hoc_symlist); + if (hoc_symlist != hoc_built_in_symlist) { + Objectdata* sav = hoc_objectdata; + hoc_objectdata = NULL; + load(type, hoc_built_in_symlist); + hoc_objectdata = sav; + } + if (hoc_symlist != hoc_top_level_symlist) { + load(type, hoc_top_level_symlist); + } + } +} + +void SymDirectoryImpl::load(int type, Symlist* sl) { + for (Symbol* sym = sl->first; sym; sym = sym->next) { + if (type == -1) { + switch (sym->type) { + case SECTION: + case OBJECTVAR: + case VAR: + case TEMPLATE: + append(sym, hoc_objectdata); + } + } else if (sym->type == type) { + append(sym, hoc_objectdata); + } + } +} + +void SymDirectoryImpl::load_object() { + Symlist* sl = obj_->ctemplate->symtable; + Objectdata* od; + if (obj_->ctemplate->constructor) { + od = NULL; + } else { + od = obj_->u.dataspace; + } + if (obj_->aliases) { + load_aliases(); + } + if (sl) + for (Symbol* s = sl->first; s; s = s->next) { + if (s->cpublic) { + append(s, od, obj_); + } + } +} + +void SymDirectoryImpl::load_aliases() { + IvocAliases* a = (IvocAliases*) obj_->aliases; + if (!a) + return; + for (const auto& [_, s]: a->symtab_) { + append(s, nullptr, obj_); + } +} + +void SymDirectoryImpl::load_template() { + hoc_Item* q; + ITERATE(q, t_->olist) { + append(OBJ(q)); + } +} + +void SymDirectoryImpl::load_section() { + char xarg[20]; + char buf[100]; + Section* sec = sec_; + int n = sec->nnode; + + int i = 0; + double x = nrn_arc_position(sec, sec->pnode[0]); + Sprintf(xarg, "( %g )", x); + Sprintf(buf, "v%s", xarg); + symbol_lists_.push_back(new SymbolItem(buf)); + nrn_pushsec(sec); + Node* nd = sec->pnode[i]; + for (const Prop* p = nd->prop; p; p = p->next) { + load_mechanism(p, 0, xarg); + } + nrn_popsec(); +} + +void SymDirectoryImpl::load_mechanism(const Prop* p, int vartype, const char* xarg) { + int type = p->_type; + if (memb_func[type].is_point) { + return; + } + char buf[200]; + Symbol* msym = memb_func[type].sym; + int cnt = msym->s_varn; + for (int i = 0; i < cnt; ++i) { + const Symbol* sym = msym->u.ppsym[i]; + if (nrn_vartype(sym) == vartype || vartype == 0) { + if (ISARRAY(sym)) { + int n = hoc_total_array_data(sym, 0); + if (n > 5) { + Sprintf(buf, "%s[all]%s", sym->name, xarg); + symbol_lists_.push_back(new SymbolItem(buf, n)); + } + Sprintf(buf, "%s[%d]%s", sym->name, 0, xarg); + symbol_lists_.push_back(new SymbolItem(buf)); + Sprintf(buf, "%s[%d]%s", sym->name, n - 1, xarg); + symbol_lists_.push_back(new SymbolItem(buf)); + } else { + Sprintf(buf, "%s%s", sym->name, xarg); + symbol_lists_.push_back(new SymbolItem(buf)); + } + } + } +} + +void SymDirectoryImpl::append(Symbol* sym, Objectdata* od, Object* o) { + if (ISARRAY(sym)) { + int i, n = 1; + if (od) { + n = hoc_total_array_data(sym, od); + } else { // Vector + if (is_obj_type(o, "Vector")) { + extern int ivoc_vector_size(Object*); + n = ivoc_vector_size(o); + } + } + if (n > 5 && sym->type == VAR) { + symbol_lists_.push_back(new SymbolItem(sym, od, 0, n)); + } + for (i = 0; i < n; ++i) { + symbol_lists_.push_back(new SymbolItem(sym, od, i)); + if (i > 5) { + break; + } + } + if (i < n - 1) { + symbol_lists_.push_back(new SymbolItem(sym, od, n - 1)); + } + } else { + symbol_lists_.push_back(new SymbolItem(sym, od, 0)); + } +} + +void SymDirectoryImpl::append(Object* ob) { + symbol_lists_.push_back(new SymbolItem(ob)); +} +void SymDirectoryImpl::un_append(Object* ob) { + for (auto& symbol: symbol_lists_) { + if (symbol->object() == ob) { + symbol->no_object(); + break; + } + } +} diff --git a/src/ivoc/symdir.h b/src/nrniv/symdir.h similarity index 100% rename from src/ivoc/symdir.h rename to src/nrniv/symdir.h diff --git a/src/oc/classreg.h b/src/oc/classreg.h index fbb4beb706..4a1893c4af 100644 --- a/src/oc/classreg.h +++ b/src/oc/classreg.h @@ -1,10 +1,8 @@ #pragma once -#include #include #include - extern void class2oc(const char*, void* (*cons)(Object*), void (*destruct)(void*), From 2305f96c533e57e2f2123a8439cd50221c54ab4f Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Thu, 25 Apr 2024 10:05:11 +0200 Subject: [PATCH 54/62] Disable building of NMODL python bindings by default (#2850) - To speed-up build from the source, we are disabling the building of NMODL python bindings. - Binary distributions like wheels are still shipping Python bindings by default. - Use the`-DNMODL_ENABLE_PYTHON_BINDINGS=ON` CMake option to enable bindings. - Update nmodl submodule - Add one integration test for nmodl with sparse solver - PYTHONPATH was not preserved in coreneuron's makefile for nmodl - add dependency with sympy in setup.py as coreneuron needs it always - nitpick: reduce `xcrun` related warning to /dev/null --- bin/nrnivmodl.in | 2 +- bin/nrnivmodl_core_makefile.in | 2 +- docs/cmake_doc/options.rst | 4 ++-- docs/coreneuron/installation.rst | 3 --- docs/install/mac_pkg.md | 6 ++++++ external/nmodl | 2 +- packaging/python/build_wheels.bash | 1 + packaging/python/test_wheels.sh | 2 ++ setup.py | 16 +++++++++++++++- share/lib/python/scripts/_binwrapper.py | 4 ++++ src/coreneuron/CMakeLists.txt | 4 ++-- 11 files changed, 35 insertions(+), 11 deletions(-) diff --git a/bin/nrnivmodl.in b/bin/nrnivmodl.in index 3df1ad6e4e..6ba80d444e 100755 --- a/bin/nrnivmodl.in +++ b/bin/nrnivmodl.in @@ -34,7 +34,7 @@ export prefix export bindir export libdir -if command -v xcrun; then +if command -v xcrun >/dev/null 2>&1; then @NRN_OSX_BUILD_TRUE@export SDKROOT=$(xcrun --sdk macosx --show-sdk-path) @NRN_OSX_BUILD_TRUE@export MACOSX_DEPLOYMENT_TARGET="@CMAKE_OSX_DEPLOYMENT_TARGET@" if [ -z "${MACOSX_DEPLOYMENT_TARGET}" ]; then diff --git a/bin/nrnivmodl_core_makefile.in b/bin/nrnivmodl_core_makefile.in index 089cd6834f..86a5138d70 100644 --- a/bin/nrnivmodl_core_makefile.in +++ b/bin/nrnivmodl_core_makefile.in @@ -71,7 +71,7 @@ CXX_LINK_EXE_CMD = $(CXX) $(CXXFLAGS) @CMAKE_EXE_LINKER_FLAGS@ CXX_SHARED_LIB_CMD = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ @CMAKE_SHARED_LIBRARY_CXX_FLAGS@ @CMAKE_SHARED_LINKER_FLAGS@ # env variables required for mod2c or nmodl -NMODL_ENV_VAR = @CORENRN_SANITIZER_ENABLE_ENVIRONMENT_STRING@ PYTHONPATH=@CORENRN_NMODL_PYTHONPATH@:${CORENRN_LIB_DIR}/python MODLUNIT=$(CORENRN_SHARE_NMODL_DIR)/nrnunits.lib +NMODL_ENV_VAR = @CORENRN_SANITIZER_ENABLE_ENVIRONMENT_STRING@ PYTHONPATH=${PYTHONPATH}:@CORENRN_NMODL_PYTHONPATH@:${CORENRN_LIB_DIR}/python MODLUNIT=$(CORENRN_SHARE_NMODL_DIR)/nrnunits.lib ifeq (@CORENRN_ENABLE_GPU@, ON) nmodl_arguments_c=@NMODL_ACC_BACKEND_ARGS@ @NMODL_COMMON_ARGS@ diff --git a/docs/cmake_doc/options.rst b/docs/cmake_doc/options.rst index 1d9bfba9e6..7a1ef1e449 100644 --- a/docs/cmake_doc/options.rst +++ b/docs/cmake_doc/options.rst @@ -404,8 +404,8 @@ NMODL options To see all the NMODL CMake options you can look in https://github.com/BlueBrain/nmodl/blob/master/CMakeLists.txt. -NMODL_ENABLE_PYTHON_BINDINGS:BOOL=ON ------------------------------------- +NMODL_ENABLE_PYTHON_BINDINGS:BOOL=OFF +------------------------------------- Enable pybind11 based python bindings Using this option the user can use the NMODL python package to use NMODL via python. For more information look at diff --git a/docs/coreneuron/installation.rst b/docs/coreneuron/installation.rst index 0eb00f3fc4..721024b0d9 100644 --- a/docs/coreneuron/installation.rst +++ b/docs/coreneuron/installation.rst @@ -31,9 +31,6 @@ Installing from source ********************** To enable CoreNEURON when building NEURON, simply pass the ``-DNRN_ENABLE_CORENEURON=ON`` option to CMake. -By default, CoreNEURON will use the `mod2c `_ source-to-source compiler to translate MOD files into C++ code. -To use the more modern `NMODL `_ source-to-source compiler, you should additionally pass ``-DCORENRN_ENABLE_NMODL=ON`` to CMake. - Most of CoreNEURON's build dependencies (Bison, Flex, CMake, Python, MPI (optional), ...) are already dependencies of NEURON, but you may want to use a specialised compiler to get optimal performance. To enable GPU support the `NVIDIA HPC SDK `_. is also required. diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index 8f69c73c64..86cee22d88 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -52,6 +52,12 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ ``` [^1] [^1]: NRN_RX3D_OPT_LEVEL=2 can build VERY slowly (cython translated cpp file can take a half hour or more). So for testing, we generally copy the script to temp.sh and modify to NRN_RX3D_OPT_LEVEL=0 +In order to build CoreNEURON support, one must add following options: +``` +-DLINK_AGAINST_PYTHON=OFF \ +-DNMODL_ENABLE_PYTHON_BINDINGS=ON \ +-DNRN_ENABLE_CORENEURON=ON +``` The default variables above will be ``` diff --git a/external/nmodl b/external/nmodl index f6821cea1a..2fb037e1f8 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit f6821cea1af81eb3061fbfff6552f0c776ef7626 +Subproject commit 2fb037e1f8d60d522ba16bd968c69a318ce5a827 diff --git a/packaging/python/build_wheels.bash b/packaging/python/build_wheels.bash index 007fa581ce..8925b3e49f 100755 --- a/packaging/python/build_wheels.bash +++ b/packaging/python/build_wheels.bash @@ -144,6 +144,7 @@ build_wheel_osx() { if [ "$2" == "coreneuron" ]; then setup_args="--enable-coreneuron" clone_install_nmodl_requirements + CMAKE_DEFS="${CMAKE_DEFS},LINK_AGAINST_PYTHON=OFF" fi CMAKE_DEFS="NRN_MPI_DYNAMIC=$3" diff --git a/packaging/python/test_wheels.sh b/packaging/python/test_wheels.sh index 3e458d1f2a..0fb3adae69 100755 --- a/packaging/python/test_wheels.sh +++ b/packaging/python/test_wheels.sh @@ -74,6 +74,8 @@ run_mpi_test () { # coreneuron execution via neuron if [[ "$has_coreneuron" == "true" ]]; then rm -rf $ARCH_DIR + # also copy one MOD file containing sparse solver + cp share/examples/nrniv/nmodl/capmp.mod "test/coreneuron/mod files/" nrnivmodl -coreneuron "test/coreneuron/mod files/" $mpi_launcher -n 1 $python_exe test/coreneuron/test_direct.py diff --git a/setup.py b/setup.py index bccf1bed53..614b57d2b9 100644 --- a/setup.py +++ b/setup.py @@ -509,7 +509,21 @@ def setup_package(): else "node-and-date" }, cmdclass=dict(build_ext=CMakeAugmentedBuilder, docs=Docs), - install_requires=["numpy>=1.9.3", "packaging", "find_libpython", "setuptools"], + install_requires=[ + "numpy>=1.9.3", + "packaging", + "find_libpython", + "setuptools", + ] + + ( + [ + "sympy>=1.3", + "importlib_resources;python_version<'3.9'", + "importlib_metadata;python_version<'3.9'", + ] + if Components.CORENRN + else [] + ), tests_require=["flake8", "pytest"], setup_requires=["wheel", "setuptools_scm"] + maybe_docs diff --git a/share/lib/python/scripts/_binwrapper.py b/share/lib/python/scripts/_binwrapper.py index bd4f200265..1fb7e417ab 100755 --- a/share/lib/python/scripts/_binwrapper.py +++ b/share/lib/python/scripts/_binwrapper.py @@ -87,6 +87,10 @@ def _config_exe(exe_name): if "NMODL_PYLIB" not in os.environ: os.environ["NMODL_PYLIB"] = find_libpython() + # nmodl module is inside /lib directory + sys.path.insert(0, os.path.join(NRN_PREFIX, "lib")) + os.environ["PYTHONPATH"] = ":".join(sys.path) + _set_default_compiler() return os.path.join(NRN_PREFIX, "bin", exe_name) diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index 737fe30485..3594329de6 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -265,8 +265,8 @@ if(nmodl_FOUND) set(CORENRN_NMODL_PYTHONPATH $ENV{PYTHONPATH}) else() set(NMODL_ENABLE_PYTHON_BINDINGS - ON - CACHE BOOL "Disable NMODL python bindings") + OFF + CACHE BOOL "Enable NMODL python bindings") nrn_add_external_project(nmodl OFF) add_subdirectory(${PROJECT_SOURCE_DIR}/external/nmodl ${CMAKE_BINARY_DIR}/external/nmodl) set(CORENRN_NMODL_BINARY ${CMAKE_BINARY_DIR}/bin/nmodl${CMAKE_EXECUTABLE_SUFFIX}) From 8b35309de3379b26fd03d1af270b735cd41f71fc Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 25 Apr 2024 13:45:50 +0200 Subject: [PATCH 55/62] std::signal define the type of the signal handler (#2855) --- cmake/ConfigFileSetting.cmake | 5 ----- cmake/MacroHelper.cmake | 17 ----------------- cmake_nrnconf.h.in | 3 --- external/iv | 2 +- src/oc/hoc.cpp | 16 ++++++++-------- 5 files changed, 9 insertions(+), 34 deletions(-) diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index d456b16d9b..0e831c0861 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -144,11 +144,6 @@ nrn_check_type_exists(sys/types.h pid_t int pid_t) nrn_check_type_exists(sys/types.h size_t "unsigned int" size_t) nrn_check_type_exists(sys/types.h uid_t int uid_t) -# ============================================================================= -# Set return type of signal in RETSIGTYPE -# ============================================================================= -nrn_check_signal_return_type(RETSIGTYPE) - # ============================================================================= # Generate file from file.in template # ============================================================================= diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index df309c19c7..b077ab909d 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -62,23 +62,6 @@ macro(nrn_check_type_exists HEADER TYPE DEFAULT_TYPE VARIABLE) file(REMOVE "conftest.cpp") endmacro() -# ============================================================================= -# Check return type of signal -# ============================================================================= -macro(nrn_check_signal_return_type VARIABLE) - # code template to check signal support - string(CONCAT CONFTEST_RETSIGTYPE "#include \n" "#include \n" - "int main () {\n" " return *(signal (0, 0)) (0) == 1\;\n" "}\n") - file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp ${CONFTEST_RETSIGTYPE}) - try_compile(MY_RESULT_VAR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp) - if(MY_RESULT_VAR) - set(${VARIABLE} int) - else() - set(${VARIABLE} void) - endif() - file(REMOVE "conftest.cpp") -endmacro() - # ============================================================================= # Perform check_include_files and add it to NRN_HEADERS_INCLUDE_LIST if exist Passing an optional # CXX will call check_include_files_cxx instead. diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 18bccb7b55..5bbd435916 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -81,9 +81,6 @@ /* Define to the version of this package. */ #cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ -/* Define as the return type of signal handlers (`int' or `void'). */ -#cmakedefine RETSIGTYPE @RETSIGTYPE@ - /* Define SUNDIALS data type 'realtype' as 'long double' */ #cmakedefine SUNDIALS_DOUBLE_PRECISION @SUNDIALS_DOUBLE_PRECISION@ diff --git a/external/iv b/external/iv index 67b6b20ed8..ad4d9223b3 160000 --- a/external/iv +++ b/external/iv @@ -1 +1 @@ -Subproject commit 67b6b20ed8784da3a8070cc1042f65e11cdf8b08 +Subproject commit ad4d9223b3c94ab5906e8f25f8ad1698160b6338 diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 29ecd12c16..322522c507 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -188,7 +188,7 @@ static int backslash(int c); #endif #if HAS_SIGPIPE /*ARGSUSED*/ -static RETSIGTYPE sigpipe_handler(int sig) { +static void sigpipe_handler(int sig) { fprintf(stderr, "writing to a broken pipe\n"); signal(SIGPIPE, sigpipe_handler); } @@ -653,7 +653,7 @@ void hoc_execerror(const char* s, const char* t) /* recover from run-time error hoc_execerror_mes(s, t, hoc_execerror_messages); } -RETSIGTYPE onintr(int sig) /* catch interrupt */ +void onintr(int /* sig */) /* catch interrupt */ { /*ARGSUSED*/ stoprun = 1; @@ -728,7 +728,7 @@ void print_bt() { #endif } -RETSIGTYPE fpecatch(int sig) /* catch floating point exceptions */ +void fpecatch(int /* sig */) /* catch floating point exceptions */ { /*ARGSUSED*/ #if DOS @@ -746,7 +746,8 @@ RETSIGTYPE fpecatch(int sig) /* catch floating point exceptions */ execerror("Floating point exception.", (char*) 0); } -RETSIGTYPE sigsegvcatch(int sig) /* segmentation violation probably due to arg type error */ +__attribute__((noreturn)) void sigsegvcatch(int /* sig */) /* segmentation violation probably due to + arg type error */ { Fprintf(stderr, "Segmentation violation\n"); print_bt(); @@ -758,7 +759,7 @@ RETSIGTYPE sigsegvcatch(int sig) /* segmentation violation probably due to arg t } #if HAVE_SIGBUS -RETSIGTYPE sigbuscatch(int sig) { +__attribute__((noreturn)) void sigbuscatch(int /* sig */) { Fprintf(stderr, "Bus error\n"); print_bt(); /*ARGSUSED*/ @@ -1170,9 +1171,8 @@ int hoc_moreinput() { return 1; } -typedef RETSIGTYPE (*SignalType)(int); - -static SignalType signals[4]; +using SignalType = void(int); +static SignalType* signals[4]; static void set_signals(void) { signals[0] = signal(SIGINT, onintr); From 13654b316c8838b16b9301507600431c4c74a0b2 Mon Sep 17 00:00:00 2001 From: MikeG Date: Mon, 29 Apr 2024 12:26:13 +0200 Subject: [PATCH 56/62] Cleanup `#include` cpp file (#2857) * Create a Parallel list of files * Remove symlink cpp files that were there for autotools --- cmake/NeuronFileLists.cmake | 38 ++++--- src/ivoc/ivocman1.cpp | 7 -- src/modlunit/units.cpp | 5 +- src/mswin/CMakeLists.txt | 4 +- src/mswin/extra/d2upath.cpp | 11 +- src/mswin/extra/d2upath.h | 1 + src/mswin/extra/mos2nrn.cpp | 2 +- src/mswin/extra/neuron.cpp | 6 +- src/nmodl/units.cpp | 6 -- src/nrncvode/hocevent.cpp | 186 ---------------------------------- src/nrncvode/netcvode.cpp | 181 ++++++++++++++++++++++++++++++++- src/nrniv/CMakeLists.txt | 7 +- src/nrniv/bbs.cpp | 1 - src/nrniv/bbsdirect.cpp | 4 - src/nrniv/bbslocal.cpp | 1 - src/nrniv/bbslsrv.cpp | 1 - src/nrniv/bbslsrv2.cpp | 4 - src/nrniv/bbsrcli.cpp | 4 - src/nrniv/bbssrv.cpp | 2 - src/nrniv/multisend_setup.cpp | 2 - src/nrniv/ocbbs.cpp | 1 - src/nrnoc/multicore.cpp | 1 - src/oc/mswinprt.cpp | 2 +- src/parallel/ocbbs.cpp | 111 +++++++++++++++++++- src/parallel/subworld.cpp | 112 -------------------- 25 files changed, 334 insertions(+), 366 deletions(-) delete mode 100644 src/ivoc/ivocman1.cpp create mode 100644 src/mswin/extra/d2upath.h delete mode 100755 src/nmodl/units.cpp delete mode 100644 src/nrncvode/hocevent.cpp delete mode 100755 src/nrniv/bbs.cpp delete mode 100755 src/nrniv/bbsdirect.cpp delete mode 100755 src/nrniv/bbslocal.cpp delete mode 100755 src/nrniv/bbslsrv.cpp delete mode 100755 src/nrniv/bbslsrv2.cpp delete mode 100755 src/nrniv/bbsrcli.cpp delete mode 100755 src/nrniv/bbssrv.cpp delete mode 100755 src/nrniv/ocbbs.cpp delete mode 100644 src/parallel/subworld.cpp diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index fe41a53a55..22f87449a2 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -204,14 +204,7 @@ endif() # ============================================================================= set(NRNIV_FILE_LIST backtrace_utils.cpp - bbs.cpp bbsavestate.cpp - bbsdirect.cpp - bbslocal.cpp - bbslsrv.cpp - bbslsrv2.cpp - bbsrcli.cpp - bbssrv.cpp classreg.cpp cxprop.cpp datapath.cpp @@ -243,7 +236,6 @@ set(NRNIV_FILE_LIST nvector_nrnserial_ld.cpp nvector_nrnthread.cpp nvector_nrnthread_ld.cpp - ocbbs.cpp ocjump.cpp partrans.cpp ppshape.cpp @@ -424,7 +416,6 @@ set(NMODL_FILES_LIST simultan.cpp solve.cpp symbol.cpp - units.cpp version.cpp) set(IVOS_FILES_LIST observe.cpp resource.cpp) @@ -433,6 +424,16 @@ set(MPI_DYNAMIC_INCLUDE nrnmpi_dynam.h nrnmpi_dynam_cinc nrnmpi_dynam_wrappers.i set(NRN_MUSIC_FILES_LIST nrnmusic.cpp) +set(NRN_PARALLEL_FILES_LIST + bbs.cpp + bbsclimpi.cpp + bbsdirectmpi.cpp + bbslocal.cpp + bbslsrv.cpp + bbssrv2mpi.cpp + bbssrvmpi.cpp + ocbbs.cpp) + # ============================================================================= # Top level directories under src # ============================================================================= @@ -447,6 +448,7 @@ set(NRN_MODLUNIT_SRC_DIR ${PROJECT_SOURCE_DIR}/src/modlunit) set(NRN_NMODL_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nmodl) set(NRN_IVOS_SRC_DIR ${PROJECT_SOURCE_DIR}/src/ivos) set(NRN_MUSIC_SRC_DIR ${PROJECT_SOURCE_DIR}/src/neuronmusic) +set(NRN_PARALLEL_SRC_DIR ${PROJECT_SOURCE_DIR}/src/parallel) # ============================================================================= # Create source file lists by gathering from various directories @@ -460,10 +462,13 @@ nrn_create_file_list(NRN_NODEORDEROPTIM_SRC_FILES ${NRN_NODEORDEROPTIM_SRC_DIR} list(APPEND NRN_NODEORDEROPTIM_SRC_FILES ${PROJECT_SOURCE_DIR}/src/coreneuron/utils/lpt.cpp) nrn_create_file_list(NRN_NRNCVODE_SRC_FILES ${NRN_NRNCVODE_SRC_DIR} ${NRNCVODE_FILE_LIST}) nrn_create_file_list(NRN_NRNIV_SRC_FILES ${NRN_NRNIV_SRC_DIR} ${NRNIV_FILE_LIST}) -nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/nrniv - nvector_nrnparallel_ld.cpp) -nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/sundials/shared - nvector_parallel.c) +nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${NRN_PARALLEL_SRC_DIR} ${NRN_PARALLEL_FILES_LIST}) +if(NRN_ENABLE_MPI) + nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/nrniv + nvector_nrnparallel_ld.cpp) + nrn_create_file_list(NRN_PARALLEL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/sundials/shared + nvector_parallel.c) +endif() nrn_create_file_list(NRN_SPARSE_SRC_FILES ${PROJECT_SOURCE_DIR}/src/sparse ${SPARSE_FILES_LIST}) nrn_create_file_list(NRN_SCOPMATH_SRC_FILES ${PROJECT_SOURCE_DIR}/src/scopmath ${SCOPMATH_FILES_LIST}) @@ -480,6 +485,7 @@ nrn_create_file_list(NRNMPI_DYNAMIC_INCLUDE_FILE ${PROJECT_SOURCE_DIR}/src/nrnmp nrn_create_file_list(NRN_IVOS_SRC_FILES ${NRN_IVOS_SRC_DIR} ${IVOS_FILES_LIST}) nrn_create_file_list(NRN_MUSIC_SRC_FILES ${NRN_MUSIC_SRC_DIR} ${NRN_MUSIC_FILES_LIST}) list(APPEND NRN_OC_SRC_FILES ${PROJECT_BINARY_DIR}/src/oc/hocusr.h) +list(APPEND NRN_NMODL_SRC_FILES ${NRN_MODLUNIT_SRC_DIR}/units.cpp) # ============================================================================= # Create mswin install lists needed for setup_exe target @@ -487,7 +493,13 @@ list(APPEND NRN_OC_SRC_FILES ${PROJECT_BINARY_DIR}/src/oc/hocusr.h) if(MINGW) set(MSWIN_SRC_DIR ${PROJECT_SOURCE_DIR}/src/mswin) nrn_create_file_list(MSWIN_FILES ${PROJECT_SOURCE_DIR}/src/parallel test0.hoc test0.py) + list(APPEND MSWIN_FILES ${MSWIN_SRC_DIR}/notes.txt) + + list(APPEND NRN_MODLUNIT_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) + list(APPEND NRN_NMODL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) + list(APPEND NRN_OC_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) + nrn_create_file_list(MSWIN_BIN_FILES ${MSWIN_SRC_DIR} nrniv.ico nrniv10.ico nmodl2a.ico) nrn_create_file_list( MSWIN_LIB_FILES diff --git a/src/ivoc/ivocman1.cpp b/src/ivoc/ivocman1.cpp deleted file mode 100644 index b191de0f60..0000000000 --- a/src/ivoc/ivocman1.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// The problem this hack overcomes is that extending Python requires -// ivocmain.cpp in the shared library (compiled with PIC) and that is -// fine for normal neuron as well. But there are link problems when -// built statically and hence ivocmain.cpp is listed in the -// ivoc_SOURCES so that it is sure to be linked early in the process. - -#include "ivocmain.cpp" diff --git a/src/modlunit/units.cpp b/src/modlunit/units.cpp index 9901f19fae..062b8efa20 100644 --- a/src/modlunit/units.cpp +++ b/src/modlunit/units.cpp @@ -13,8 +13,9 @@ #include #ifdef MINGW -#include "../mswin/extra/d2upath.cpp" +#include "../mswin/extra/d2upath.h" #endif + #if defined(WIN32) #include #endif @@ -109,7 +110,7 @@ static int Getc(FILE* inp) { static struct unit unit_stack[UNIT_STK_SIZE], *usp{nullptr}; static char* neuronhome() { -#if defined(WIN32) +#if defined(MINGW) int i; static char buf[256]; GetModuleFileName(NULL, buf, 256); diff --git a/src/mswin/CMakeLists.txt b/src/mswin/CMakeLists.txt index 94669e77d0..b660eaed4c 100644 --- a/src/mswin/CMakeLists.txt +++ b/src/mswin/CMakeLists.txt @@ -31,8 +31,8 @@ if(MINGW) DEPENDS ${mswinsrc}/nrniv10.ico) set_source_files_properties(${mswinsrc}/extra/neuron.cpp ${mswinsrc}/extra/mos2nrn.cpp ${mswinsrc}/extra/nrnbinstr.cpp PROPERTIES COMPILE_DEFINITIONS MINGW) - add_executable(neuron ${mswinsrc}/extra/neuron.cpp nrnicon.res) - add_executable(mos2nrn ${mswinsrc}/extra/mos2nrn.cpp) + add_executable(neuron ${mswinsrc}/extra/neuron.cpp ${mswinsrc}/extra/d2upath.cpp nrnicon.res) + add_executable(mos2nrn ${mswinsrc}/extra/mos2nrn.cpp ${mswinsrc}/extra/d2upath.cpp) add_executable(nrnbinstr ${mswinsrc}/extra/nrnbinstr.cpp) set(INCDIRS ${PROJECT_SOURCE_DIR}/src/oc) target_include_directories(mos2nrn PUBLIC ${INCDIRS}) diff --git a/src/mswin/extra/d2upath.cpp b/src/mswin/extra/d2upath.cpp index 9b9ce5c064..8c5d929b4d 100644 --- a/src/mswin/extra/d2upath.cpp +++ b/src/mswin/extra/d2upath.cpp @@ -5,18 +5,19 @@ up to 11 characters longer. the output string should be freed with free() when no longer needed. */ -#include -#include -#include +#include +#include +#include char* hoc_dos2unixpath(const char* d) { /* translate x: and x:/ and x:\, to /cygdrive/x/ */ /* and all backslashes to forward slashes */ /* or, for mingw, just backslashes to forward slashes */ - char* cp; + char* cp = nullptr; auto* const u = static_cast(malloc(strlen(d) + 12)); assert(u); - int i{}, j{}; + size_t i = 0; + int j = 0; if (d[0] && d[1] == ':') { strcpy(u, "/cygdrive/"); i = strlen(u); diff --git a/src/mswin/extra/d2upath.h b/src/mswin/extra/d2upath.h new file mode 100644 index 0000000000..c1374dcfff --- /dev/null +++ b/src/mswin/extra/d2upath.h @@ -0,0 +1 @@ +char* hoc_dos2unixpath(const char* d); diff --git a/src/mswin/extra/mos2nrn.cpp b/src/mswin/extra/mos2nrn.cpp index aa3d5072ec..37cb0d2069 100644 --- a/src/mswin/extra/mos2nrn.cpp +++ b/src/mswin/extra/mos2nrn.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "d2upath.cpp" +#include "d2upath.h" char* nrnhome; char* nh; diff --git a/src/mswin/extra/neuron.cpp b/src/mswin/extra/neuron.cpp index cd5f52b94a..50224d6fb4 100644 --- a/src/mswin/extra/neuron.cpp +++ b/src/mswin/extra/neuron.cpp @@ -5,12 +5,12 @@ // finally executes nrniv.exe. Nrniv.exe can be run by itself if // it does not need a console or system("command") #include -#include -#include -#include "d2upath.cpp" +#include "d2upath.h" #include +#include +#include char* nrnhome; char* nh; diff --git a/src/nmodl/units.cpp b/src/nmodl/units.cpp deleted file mode 100755 index a618b6e73b..0000000000 --- a/src/nmodl/units.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include <../../nrnconf.h> -/* - * Automake doesn't deal well with sources that live in other directories. - * This is a quick and dirty workaround. - */ -#include "../modlunit/units.cpp" diff --git a/src/nrncvode/hocevent.cpp b/src/nrncvode/hocevent.cpp deleted file mode 100644 index 5654ea0b7d..0000000000 --- a/src/nrncvode/hocevent.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include -#include -#include -#include - -using HocEventPool = MutexPool; -HocEventPool* HocEvent::hepool_; - -HocEvent::HocEvent() { - stmt_ = nullptr; - ppobj_ = nullptr; - reinit_ = 0; -} - -HocEvent::~HocEvent() { - if (stmt_) { - delete stmt_; - } -} - -void HocEvent::pr(const char* s, double tt, NetCvode* ns) { - Printf("%s HocEvent %s %.15g\n", s, stmt_ ? stmt_->name() : "", tt); -} - -HocEvent* HocEvent::alloc(const char* stmt, Object* ppobj, int reinit, Object* pyact) { - if (!hepool_) { - nrn_hoc_lock(); - if (!hepool_) { - hepool_ = new HocEventPool(100, 1); - } - nrn_hoc_unlock(); - } - HocEvent* he = hepool_->alloc(); - he->stmt_ = nullptr; - he->ppobj_ = ppobj; - he->reinit_ = reinit; - if (pyact) { - he->stmt_ = new HocCommand(pyact); - } else if (stmt) { - he->stmt_ = new HocCommand(stmt); - } - return he; -} - -void HocEvent::hefree() { - if (stmt_) { - delete stmt_; - stmt_ = nullptr; - } - hepool_->hpfree(this); -} - -void HocEvent::clear() { - if (stmt_) { - delete stmt_; - stmt_ = nullptr; - } -} - -void HocEvent::deliver(double tt, NetCvode* nc, NrnThread* nt) { - extern double t; - if (!ppobj_) { - nc->allthread_handle(tt, this, nt); - return; - } - if (stmt_) { - if (nrn_nthread > 1 || nc->is_local()) { - if (!ppobj_) { - hoc_execerror( - "multiple threads and/or local variable time step method require an " - "appropriate POINT_PROCESS arg to CVode.event to safely execute:", - stmt_->name()); - } - Cvode* cv = (Cvode*) ob2pntproc(ppobj_)->nvi_; - if (cv && cvode_active_) { - nc->local_retreat(tt, cv); - if (reinit_) { - cv->set_init_flag(); - } - nt->_t = cv->t_; - } - nrn_hoc_lock(); - t = tt; - } else if (cvode_active_ && reinit_) { - nc->retreat(tt, nc->gcv_); - assert(MyMath::eq(tt, nc->gcv_->t_, NetCvode::eps(tt))); - assert(tt == nt->_t); - nc->gcv_->set_init_flag(); - t = tt; - } else { - t = nt_t = tt; - } - stmt_->execute(false); - if (nrn_nthread > 1 || nc->is_local()) { - nrn_hoc_unlock(); - } - } - hefree(); -} - -void HocEvent::allthread_handle() { - if (stmt_) { - stmt_->execute(false); - } else { - tstopset; - } - hefree(); -} - -void HocEvent::pgvts_deliver(double tt, NetCvode* nc) { - deliver(tt, nc, nrn_threads); -} - -void HocEvent::reclaim() { - if (hepool_) { - hepool_->free_all(); - } -} - -DiscreteEvent* HocEvent::savestate_save() { - // pr("HocEvent::savestate_save", 0, net_cvode_instance); - HocEvent* he = new HocEvent(); - if (stmt_) { - if (stmt_->pyobject()) { - he->stmt_ = new HocCommand(stmt_->pyobject()); - } else { - he->stmt_ = new HocCommand(stmt_->name(), stmt_->object()); - } - he->reinit_ = reinit_; - he->ppobj_ = ppobj_; - } - return he; -} - -void HocEvent::savestate_restore(double tt, NetCvode* nc) { - // pr("HocEvent::savestate_restore", tt, nc); - HocEvent* he = alloc(nullptr, nullptr, 0); - NrnThread* nt = nrn_threads; - if (stmt_) { - if (stmt_->pyobject()) { - he->stmt_ = new HocCommand(stmt_->pyobject()); - } else { - he->stmt_ = new HocCommand(stmt_->name(), stmt_->object()); - } - he->reinit_ = reinit_; - he->ppobj_ = ppobj_; - if (ppobj_) { - nt = (NrnThread*) ob2pntproc(ppobj_)->_vnt; - } - } - nc->event(tt, he, nt); -} - -DiscreteEvent* HocEvent::savestate_read(FILE* f) { - HocEvent* he = new HocEvent(); - int have_stmt, have_obj, index; - char stmt[256], objname[100], buf[200]; - Object* obj = nullptr; - // nrn_assert(fscanf(f, "%d %d\n", &have_stmt, &have_obj) == 2); - nrn_assert(fgets(buf, 200, f)); - nrn_assert(sscanf(buf, "%d %d\n", &have_stmt, &have_obj) == 2); - if (have_stmt) { - nrn_assert(fgets(stmt, 256, f)); - stmt[strlen(stmt) - 1] = '\0'; - if (have_obj) { - // nrn_assert(fscanf(f, "%s %d\n", objname, &index) == 1); - nrn_assert(fgets(buf, 200, f)); - nrn_assert(sscanf(buf, "%s %d\n", objname, &index) == 1); - obj = hoc_name2obj(objname, index); - } - he->stmt_ = new HocCommand(stmt, obj); - } - return he; -} - -void HocEvent::savestate_write(FILE* f) { - fprintf(f, "%d\n", HocEventType); - fprintf(f, "%d %d\n", stmt_ ? 1 : 0, (stmt_ && stmt_->object()) ? 1 : 0); - if (stmt_) { - fprintf(f, "%s\n", stmt_->name()); - if (stmt_->object()) { - fprintf(f, "%s %d\n", stmt_->object()->ctemplate->sym->name, stmt_->object()->index); - } - } -} diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index f0421a92da..ca6a9b7657 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -3396,7 +3396,186 @@ void PlayRecordEvent::pr(const char* s, double tt, NetCvode* ns) { plr_->pr(); } -#include +using HocEventPool = MutexPool; +HocEventPool* HocEvent::hepool_; + +HocEvent::HocEvent() { + stmt_ = nullptr; + ppobj_ = nullptr; + reinit_ = 0; +} + +HocEvent::~HocEvent() { + if (stmt_) { + delete stmt_; + } +} + +void HocEvent::pr(const char* s, double tt, NetCvode* ns) { + Printf("%s HocEvent %s %.15g\n", s, stmt_ ? stmt_->name() : "", tt); +} + +HocEvent* HocEvent::alloc(const char* stmt, Object* ppobj, int reinit, Object* pyact) { + if (!hepool_) { + nrn_hoc_lock(); + if (!hepool_) { + hepool_ = new HocEventPool(100, 1); + } + nrn_hoc_unlock(); + } + HocEvent* he = hepool_->alloc(); + he->stmt_ = nullptr; + he->ppobj_ = ppobj; + he->reinit_ = reinit; + if (pyact) { + he->stmt_ = new HocCommand(pyact); + } else if (stmt) { + he->stmt_ = new HocCommand(stmt); + } + return he; +} + +void HocEvent::hefree() { + if (stmt_) { + delete stmt_; + stmt_ = nullptr; + } + hepool_->hpfree(this); +} + +void HocEvent::clear() { + if (stmt_) { + delete stmt_; + stmt_ = nullptr; + } +} + +void HocEvent::deliver(double tt, NetCvode* nc, NrnThread* nt) { + extern double t; + if (!ppobj_) { + nc->allthread_handle(tt, this, nt); + return; + } + if (stmt_) { + if (nrn_nthread > 1 || nc->is_local()) { + if (!ppobj_) { + hoc_execerror( + "multiple threads and/or local variable time step method require an " + "appropriate POINT_PROCESS arg to CVode.event to safely execute:", + stmt_->name()); + } + Cvode* cv = (Cvode*) ob2pntproc(ppobj_)->nvi_; + if (cv && cvode_active_) { + nc->local_retreat(tt, cv); + if (reinit_) { + cv->set_init_flag(); + } + nt->_t = cv->t_; + } + nrn_hoc_lock(); + t = tt; + } else if (cvode_active_ && reinit_) { + nc->retreat(tt, nc->gcv_); + assert(MyMath::eq(tt, nc->gcv_->t_, NetCvode::eps(tt))); + assert(tt == nt->_t); + nc->gcv_->set_init_flag(); + t = tt; + } else { + t = nt_t = tt; + } + stmt_->execute(false); + if (nrn_nthread > 1 || nc->is_local()) { + nrn_hoc_unlock(); + } + } + hefree(); +} + +void HocEvent::allthread_handle() { + if (stmt_) { + stmt_->execute(false); + } else { + tstopset; + } + hefree(); +} + +void HocEvent::pgvts_deliver(double tt, NetCvode* nc) { + deliver(tt, nc, nrn_threads); +} + +void HocEvent::reclaim() { + if (hepool_) { + hepool_->free_all(); + } +} + +DiscreteEvent* HocEvent::savestate_save() { + // pr("HocEvent::savestate_save", 0, net_cvode_instance); + HocEvent* he = new HocEvent(); + if (stmt_) { + if (stmt_->pyobject()) { + he->stmt_ = new HocCommand(stmt_->pyobject()); + } else { + he->stmt_ = new HocCommand(stmt_->name(), stmt_->object()); + } + he->reinit_ = reinit_; + he->ppobj_ = ppobj_; + } + return he; +} + +void HocEvent::savestate_restore(double tt, NetCvode* nc) { + // pr("HocEvent::savestate_restore", tt, nc); + HocEvent* he = alloc(nullptr, nullptr, 0); + NrnThread* nt = nrn_threads; + if (stmt_) { + if (stmt_->pyobject()) { + he->stmt_ = new HocCommand(stmt_->pyobject()); + } else { + he->stmt_ = new HocCommand(stmt_->name(), stmt_->object()); + } + he->reinit_ = reinit_; + he->ppobj_ = ppobj_; + if (ppobj_) { + nt = (NrnThread*) ob2pntproc(ppobj_)->_vnt; + } + } + nc->event(tt, he, nt); +} + +DiscreteEvent* HocEvent::savestate_read(FILE* f) { + HocEvent* he = new HocEvent(); + int have_stmt, have_obj, index; + char stmt[256], objname[100], buf[200]; + Object* obj = nullptr; + // nrn_assert(fscanf(f, "%d %d\n", &have_stmt, &have_obj) == 2); + nrn_assert(fgets(buf, 200, f)); + nrn_assert(sscanf(buf, "%d %d\n", &have_stmt, &have_obj) == 2); + if (have_stmt) { + nrn_assert(fgets(stmt, 256, f)); + stmt[strlen(stmt) - 1] = '\0'; + if (have_obj) { + // nrn_assert(fscanf(f, "%s %d\n", objname, &index) == 1); + nrn_assert(fgets(buf, 200, f)); + nrn_assert(sscanf(buf, "%s %d\n", objname, &index) == 1); + obj = hoc_name2obj(objname, index); + } + he->stmt_ = new HocCommand(stmt, obj); + } + return he; +} + +void HocEvent::savestate_write(FILE* f) { + fprintf(f, "%d\n", HocEventType); + fprintf(f, "%d %d\n", stmt_ ? 1 : 0, (stmt_ && stmt_->object()) ? 1 : 0); + if (stmt_) { + fprintf(f, "%s\n", stmt_->name()); + if (stmt_->object()) { + fprintf(f, "%s %d\n", stmt_->object()->ctemplate->sym->name, stmt_->object()->index); + } + } +} void NetCvode::local_retreat(double t, Cvode* cv) { if (!cvode_active_) { diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index c9331147c3..578be1dd92 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -157,11 +157,8 @@ set(NRN_NRNIV_LIB_SRC_FILES ${NRN_MODFILE_CPP} ${NRN_SCOPMATH_SRC_FILES} ${NRN_SPARSE_SRC_FILES} - ${NRN_SUNDIALS_SRC_FILES}) - -if(NRN_ENABLE_MPI) - list(APPEND NRN_NRNIV_LIB_SRC_FILES ${NRN_PARALLEL_SRC_FILES}) -endif() + ${NRN_SUNDIALS_SRC_FILES} + ${NRN_PARALLEL_SRC_FILES}) if(NRN_ENABLE_MPI_DYNAMIC) list(APPEND NRN_NRNIV_LIB_SRC_FILES ${PROJECT_SOURCE_DIR}/src/nrnmpi/nrnmpi_dynam.cpp) diff --git a/src/nrniv/bbs.cpp b/src/nrniv/bbs.cpp deleted file mode 100755 index 2eae2b7652..0000000000 --- a/src/nrniv/bbs.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../parallel/bbs.cpp" diff --git a/src/nrniv/bbsdirect.cpp b/src/nrniv/bbsdirect.cpp deleted file mode 100755 index 6639223399..0000000000 --- a/src/nrniv/bbsdirect.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include -#if NRNMPI -#include "../parallel/bbsdirectmpi.cpp" -#endif diff --git a/src/nrniv/bbslocal.cpp b/src/nrniv/bbslocal.cpp deleted file mode 100755 index 16555d709e..0000000000 --- a/src/nrniv/bbslocal.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../parallel/bbslocal.cpp" diff --git a/src/nrniv/bbslsrv.cpp b/src/nrniv/bbslsrv.cpp deleted file mode 100755 index 84bf12f591..0000000000 --- a/src/nrniv/bbslsrv.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../parallel/bbslsrv.cpp" diff --git a/src/nrniv/bbslsrv2.cpp b/src/nrniv/bbslsrv2.cpp deleted file mode 100755 index 058c49810d..0000000000 --- a/src/nrniv/bbslsrv2.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include -#if NRNMPI -#include "../parallel/bbssrv2mpi.cpp" -#endif diff --git a/src/nrniv/bbsrcli.cpp b/src/nrniv/bbsrcli.cpp deleted file mode 100755 index 945ca5a3eb..0000000000 --- a/src/nrniv/bbsrcli.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include -#if NRNMPI -#include "../parallel/bbsclimpi.cpp" -#endif diff --git a/src/nrniv/bbssrv.cpp b/src/nrniv/bbssrv.cpp deleted file mode 100755 index a89f19c495..0000000000 --- a/src/nrniv/bbssrv.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include "../parallel/bbssrvmpi.cpp" diff --git a/src/nrniv/multisend_setup.cpp b/src/nrniv/multisend_setup.cpp index 479d30bf78..8e66681e8c 100644 --- a/src/nrniv/multisend_setup.cpp +++ b/src/nrniv/multisend_setup.cpp @@ -9,8 +9,6 @@ the source host owning the gid. */ #include "oc_ansi.h" -#include "oc_ansi.h" - static void del(int* a) { if (a) { delete[] a; diff --git a/src/nrniv/ocbbs.cpp b/src/nrniv/ocbbs.cpp deleted file mode 100755 index c7233ce4b4..0000000000 --- a/src/nrniv/ocbbs.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../parallel/ocbbs.cpp" diff --git a/src/nrnoc/multicore.cpp b/src/nrnoc/multicore.cpp index 83c8e3ff05..fc1bb40618 100644 --- a/src/nrnoc/multicore.cpp +++ b/src/nrnoc/multicore.cpp @@ -1,4 +1,3 @@ -/* included by treeset.cpp */ #include #include "hoclist.h" diff --git a/src/oc/mswinprt.cpp b/src/oc/mswinprt.cpp index 905aa101b2..29dbdc9571 100644 --- a/src/oc/mswinprt.cpp +++ b/src/oc/mswinprt.cpp @@ -12,7 +12,7 @@ #include #include #include "hoc.h" -#include "../mswin/extra/d2upath.cpp" +#include "../mswin/extra/d2upath.h" #include "gui-redirect.h" diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 7462d149b3..9f59ad7c5c 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -1354,7 +1354,116 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { return rs; } -#include "subworld.cpp" +void BBSImpl::subworld_worker_execute() { + // execute the same thing that execute_worker is executing. This + // is done for all the nrnmpi_myid_bbs == -1 workers associated with + // the specific nrnmpi_myid == 0 with nrnmpi_myid_bbs >= 0. + // All the nrnmpi/mpispike.cpp functions can be used since the + // proper communicators for a subworld are used by those functions. + // The broadcast functions are particularly useful and those are + // how execute_worker passes messages into here. + + // printf("%d enter subworld_worker_execute\n", nrnmpi_myid_world); + int info[2]; + // wait for something to do + nrnmpi_int_broadcast(info, 2, 0); + // info[0] = -1 means it was from a pc.context. Also -2 means + // DONE. + // printf("%d subworld_worker_execute info %d %d\n", nrnmpi_myid_world, info[0], info[1]); + int id = info[0]; + if (id == -2) { // DONE, so quit. + done(); + } + hoc_ac_ = double(id); + int style = info[1]; + if (style == 0) { // hoc statement form + int size; + nrnmpi_int_broadcast(&size, 1, 0); // includes terminator + char* s = new char[size]; + nrnmpi_char_broadcast(s, size, 0); + hoc_obj_run(s, nullptr); + delete[] s; + // printf("%d leave subworld_worker_execute\n", nrnmpi_myid_world); + return; + } + int i, j; + int npickle; + char* s; + Symbol* fname = 0; + Object* ob = nullptr; + char* sarg[20]; // up to 20 arguments may be strings + int ns = 0; // number of args that are strings + int narg = 0; // total number of args + + if (style == 3) { // python callable + nrnmpi_int_broadcast(&npickle, 1, 0); + s = new char[npickle]; + nrnmpi_char_broadcast(s, npickle, 0); + } else if (style == 1) { // hoc function + int size; + nrnmpi_int_broadcast(&size, 1, 0); // includes terminator + // printf("%d subworld hoc function string size = %d\n", nrnmpi_myid_world, size); + s = new char[size]; + nrnmpi_char_broadcast(s, size, 0); + fname = hoc_lookup(s); + if (!fname) { + return; + } // error raised by sender + } else { + return; // no others implemented, error raised by sender + } + + // now get the args + int argtypes; + nrnmpi_int_broadcast(&argtypes, 1, 0); + // printf("%d subworld argtypes = %d\n", nrnmpi_myid_world, argtypes); + for (j = argtypes; (i = j % 5) != 0; j /= 5) { + ++narg; + if (i == 1) { // double + double x; + nrnmpi_dbl_broadcast(&x, 1, 0); + // printf("%d subworld scalar = %g\n", nrnmpi_myid_world, x); + hoc_pushx(x); + } else if (i == 2) { // string + int size; + nrnmpi_int_broadcast(&size, 1, 0); + sarg[ns] = new char[size]; + nrnmpi_char_broadcast(sarg[ns], size, 0); + hoc_pushstr(sarg + ns); + ns++; + } else if (i == 3) { // Vector + int n; + nrnmpi_int_broadcast(&n, 1, 0); + Vect* vec = new Vect(n); + nrnmpi_dbl_broadcast(vec->data(), n, 0); + hoc_pushobj(vec->temp_objvar()); + } else { // PythonObject + int n; + nrnmpi_int_broadcast(&n, 1, 0); + char* s; + s = new char[n]; + nrnmpi_char_broadcast(s, n, 0); + Object* po = neuron::python::methods.pickle2po(s, size_t(n)); + delete[] s; + hoc_pushobj(hoc_temp_objptr(po)); + } + } + + if (style == 3) { + size_t size; + char* rs = neuron::python::methods.call_picklef(s, size_t(npickle), narg, &size); + assert(rs); + delete[] rs; + } else { + // printf("%d subworld hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, narg); + hoc_call_objfunc(fname, narg, ob); + // printf("%d subworld return from hoc call %s\n", nrnmpi_myid_world, fname->name); + } + delete[] s; + for (i = 0; i < ns; ++i) { + delete[] sarg[i]; + } +} void BBSImpl::return_args(int id) { // the message has been set up by the subclass diff --git a/src/parallel/subworld.cpp b/src/parallel/subworld.cpp deleted file mode 100644 index c9b82ef2a3..0000000000 --- a/src/parallel/subworld.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// included by ocbbs.cpp - -void BBSImpl::subworld_worker_execute() { - // execute the same thing that execute_worker is executing. This - // is done for all the nrnmpi_myid_bbs == -1 workers associated with - // the specific nrnmpi_myid == 0 with nrnmpi_myid_bbs >= 0. - // All the nrnmpi/mpispike.cpp functions can be used since the - // proper communicators for a subworld are used by those functions. - // The broadcast functions are particularly useful and those are - // how execute_worker passes messages into here. - - // printf("%d enter subworld_worker_execute\n", nrnmpi_myid_world); - int info[2]; - // wait for something to do - nrnmpi_int_broadcast(info, 2, 0); - // info[0] = -1 means it was from a pc.context. Also -2 means - // DONE. - // printf("%d subworld_worker_execute info %d %d\n", nrnmpi_myid_world, info[0], info[1]); - int id = info[0]; - if (id == -2) { // DONE, so quit. - done(); - } - hoc_ac_ = double(id); - int style = info[1]; - if (style == 0) { // hoc statement form - int size; - nrnmpi_int_broadcast(&size, 1, 0); // includes terminator - char* s = new char[size]; - nrnmpi_char_broadcast(s, size, 0); - hoc_obj_run(s, nullptr); - delete[] s; - // printf("%d leave subworld_worker_execute\n", nrnmpi_myid_world); - return; - } - int i, j; - int npickle; - char* s; - Symbol* fname = 0; - Object* ob = nullptr; - char* sarg[20]; // up to 20 arguments may be strings - int ns = 0; // number of args that are strings - int narg = 0; // total number of args - - if (style == 3) { // python callable - nrnmpi_int_broadcast(&npickle, 1, 0); - s = new char[npickle]; - nrnmpi_char_broadcast(s, npickle, 0); - } else if (style == 1) { // hoc function - int size; - nrnmpi_int_broadcast(&size, 1, 0); // includes terminator - // printf("%d subworld hoc function string size = %d\n", nrnmpi_myid_world, size); - s = new char[size]; - nrnmpi_char_broadcast(s, size, 0); - fname = hoc_lookup(s); - if (!fname) { - return; - } // error raised by sender - } else { - return; // no others implemented, error raised by sender - } - - // now get the args - int argtypes; - nrnmpi_int_broadcast(&argtypes, 1, 0); - // printf("%d subworld argtypes = %d\n", nrnmpi_myid_world, argtypes); - for (j = argtypes; (i = j % 5) != 0; j /= 5) { - ++narg; - if (i == 1) { // double - double x; - nrnmpi_dbl_broadcast(&x, 1, 0); - // printf("%d subworld scalar = %g\n", nrnmpi_myid_world, x); - hoc_pushx(x); - } else if (i == 2) { // string - int size; - nrnmpi_int_broadcast(&size, 1, 0); - sarg[ns] = new char[size]; - nrnmpi_char_broadcast(sarg[ns], size, 0); - hoc_pushstr(sarg + ns); - ns++; - } else if (i == 3) { // Vector - int n; - nrnmpi_int_broadcast(&n, 1, 0); - Vect* vec = new Vect(n); - nrnmpi_dbl_broadcast(vec->data(), n, 0); - hoc_pushobj(vec->temp_objvar()); - } else { // PythonObject - int n; - nrnmpi_int_broadcast(&n, 1, 0); - char* s; - s = new char[n]; - nrnmpi_char_broadcast(s, n, 0); - Object* po = neuron::python::methods.pickle2po(s, size_t(n)); - delete[] s; - hoc_pushobj(hoc_temp_objptr(po)); - } - } - - if (style == 3) { - size_t size; - char* rs = neuron::python::methods.call_picklef(s, size_t(npickle), narg, &size); - assert(rs); - delete[] rs; - } else { - // printf("%d subworld hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, narg); - hoc_call_objfunc(fname, narg, ob); - // printf("%d subworld return from hoc call %s\n", nrnmpi_myid_world, fname->name); - } - delete[] s; - for (i = 0; i < ns; ++i) { - delete[] sarg[i]; - } -} From 2ce1805278075f55266515fe942aec308937e022 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 1 May 2024 23:58:47 +0200 Subject: [PATCH 57/62] Fix pytest to 8.1.1 due to failure (#2866) --- external/nmodl | 2 +- nrn_requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external/nmodl b/external/nmodl index 2fb037e1f8..70553cc4d9 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit 2fb037e1f8d60d522ba16bd968c69a318ce5a827 +Subproject commit 70553cc4d9092aafed42aa49ac4e730830af1124 diff --git a/nrn_requirements.txt b/nrn_requirements.txt index 77ccb32ddc..a7d8bcbcde 100644 --- a/nrn_requirements.txt +++ b/nrn_requirements.txt @@ -8,7 +8,7 @@ bokeh<3 ipython cython<3 packaging -pytest +pytest<=8.1.1 # potential bug from 8.2.0 due to parallelism? pytest-cov mpi4py numpy From 88bce8b35d873c47a6d2d6f5464b7447b24f1492 Mon Sep 17 00:00:00 2001 From: MikeG Date: Thu, 2 May 2024 02:24:20 +0200 Subject: [PATCH 58/62] Add `nrnunits.lib` dependency to `nocmodl_mod_to_cpp` cmake macro (#2861) * otherwise, `ninja src/nrniv/CMakeFiles/nrniv_lib.dir/__/nrnoc/hh.cpp.o` fails from a clean build with: Error: Bad MODLUNIT environment variable. Cant open: [...]build/share/nrn/lib/nrnunits.lib at line 32 in file [...]nrn/src/nrnoc/oclmp.mod --- cmake/MacroHelper.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index b077ab909d..fa0623c81c 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -164,6 +164,7 @@ macro(nocmodl_mod_to_cpp modfile_basename) COMMAND ${CMAKE_COMMAND} -E ${REMOVE_CMAKE_COMMAND} ${PROJECT_SOURCE_DIR}/${modfile_basename}.cpp DEPENDS nocmodl ${PROJECT_SOURCE_DIR}/${modfile_basename}.mod + ${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src/nrniv) endmacro() From 8a9bada632e075923c7a1e8a8be9d6becb6ed7ed Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 2 May 2024 10:25:06 +0200 Subject: [PATCH 59/62] Upgrade the number of core available for GHA (#2865) --- .github/workflows/neuron-ci.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 9dcec6d953..0f813b5680 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -49,7 +49,7 @@ jobs: config: - { matrix_eval : "CC=gcc-9 CXX=g++-9", build_mode: "setuptools"} - { matrix_eval : "CC=gcc-10 CXX=g++-10", build_mode: "cmake", music: ON} - - { matrix_eval : "CC=gcc-10 CXX=g++-10", build_mode: "cmake", python_dynamic: ON} + - { matrix_eval : "CC=gcc-10 CXX=g++-10", build_mode: "cmake", python_dynamic: ON} - { matrix_eval : "CC=gcc-9 CXX=g++-9" , build_mode: "cmake", cmake_option: "-DNRN_ENABLE_CORENEURON=ON"} - { matrix_eval : "CC=gcc-9 CXX=g++-9", build_mode: "cmake", cmake_option: "-DNRN_ENABLE_MPI=OFF -DNRN_ENABLE_INTERVIEWS=OFF -DNRN_ENABLE_CORENEURON=ON"} - { matrix_eval : "CC=gcc-10 CXX=g++-10", build_mode: "cmake", cmake_option: "-DNRN_ENABLE_PYTHON=OFF -DNRN_ENABLE_RX3D=OFF -DNRN_ENABLE_CORENEURON=ON"} @@ -114,9 +114,14 @@ jobs: brew install openmpi brew install --cask xquartz echo "$(brew --prefix)/opt/flex/bin:$(brew --prefix)/opt/bison/bin" >> $GITHUB_PATH - # Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources - echo CMAKE_BUILD_PARALLEL_LEVEL=3 >> $GITHUB_ENV - echo CTEST_PARALLEL_LEVEL=3 >> $GITHUB_ENV + # Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories + if [[ "${{matrix.os}}" == "macOS-13" ]]; then + echo CMAKE_BUILD_PARALLEL_LEVEL=4 >> $GITHUB_ENV + echo CTEST_PARALLEL_LEVEL=4 >> $GITHUB_ENV + else + echo CMAKE_BUILD_PARALLEL_LEVEL=3 >> $GITHUB_ENV + echo CTEST_PARALLEL_LEVEL=3 >> $GITHUB_ENV + fi echo CI_OS_NAME=osx >> $GITHUB_ENV shell: bash @@ -130,9 +135,9 @@ jobs: if [[ "${{matrix.os}}" == "ubuntu-20.04" ]]; then sudo apt-get install g++-7 g++-8 fi - # Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources - echo CMAKE_BUILD_PARALLEL_LEVEL=2 >> $GITHUB_ENV - echo CTEST_PARALLEL_LEVEL=2 >> $GITHUB_ENV + # Core https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories + echo CMAKE_BUILD_PARALLEL_LEVEL=4 >> $GITHUB_ENV + echo CTEST_PARALLEL_LEVEL=4 >> $GITHUB_ENV echo CI_OS_NAME=linux >> $GITHUB_ENV shell: bash From 0a7b890cc5d3545b2f0e5530b6bf7a64249f6604 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 3 May 2024 18:21:17 +0200 Subject: [PATCH 60/62] Put max version of python to 3.12 for GHA (#2868) * Put max version of python to 3.12 for GHA * install setuptools for music * debug with tmate, tmate is MY mate * att automake * Fix version of python * Install automake fix * UBS * Let's go --------- Co-authored-by: Nicolas Cornu --- .github/workflows/coverage.yml | 4 ++-- .github/workflows/docs.yml | 2 +- .github/workflows/neuron-ci.yml | 19 +++++++++++++++++-- .github/workflows/windows.yml | 2 +- .sanitizers/undefined.supp | 1 + 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 550c839355..a78b6934e2 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -24,7 +24,7 @@ on: env: PY_MIN_VERSION: '3.8' PY_MID_VERSION: '3.10' - PY_MAX_VERSION: '3.11' + PY_MAX_VERSION: '3.12' jobs: coverage: @@ -58,7 +58,7 @@ jobs: run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install mpi4py "cython<3" numpy + python3 -m pip install mpi4py "cython<3" numpy setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4fad29b18e..dffa17c6fa 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ on: - release/** env: - DEFAULT_PY_VERSION: '3.11' + DEFAULT_PY_VERSION: '3.12' jobs: documentation: diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 0f813b5680..f702b71872 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -39,7 +39,7 @@ jobs: DESIRED_CMAKE_VERSION: 3.17 DYNAMIC_PYTHON_CMAKE_VERSION: 3.18 PY_MIN_VERSION: ${{ matrix.config.python_min_version || '3.8' }} - PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.11' }} + PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.12' }} MUSIC_INSTALL_DIR: /opt/MUSIC MUSIC_VERSION: 1.2.1 @@ -176,12 +176,27 @@ jobs: python -m pip install --upgrade -r external/nmodl/requirements.txt python -m pip install --upgrade -r ci_requirements.txt + - name: Install a new automake + # A new automake is needed for python 3.12 because it generate a python script + # called py-compile and the original one is not supporting this version of python + # Once ubuntu got a newer version of automake we can remove this part. + if: matrix.config.music == 'ON' && startsWith(matrix.os, 'ubuntu') + run: | + curl -L -o automake.tar.xz https://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.xz + tar -xf automake.tar.xz + cd automake-1.16.5/ + ./configure --prefix=/usr/ + make -j + sudo make -j install + automake --version + working-directory: ${{runner.temp}} + - name: Setup MUSIC@${{ env.MUSIC_VERSION }} if: matrix.config.music == 'ON' run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install mpi4py "cython<3" numpy + python3 -m pip install mpi4py "cython<3" numpy setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 499ba667b0..985eae0ae0 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -49,7 +49,7 @@ jobs: - name: Set up Python3 uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - name: Download Dependencies run: | diff --git a/.sanitizers/undefined.supp b/.sanitizers/undefined.supp index 1cf1be5119..1e7ab0b39a 100644 --- a/.sanitizers/undefined.supp +++ b/.sanitizers/undefined.supp @@ -30,6 +30,7 @@ shift-base:nrnRan4int unsigned-integer-overflow:_philox4x32bumpkey(r123array2x32) unsigned-integer-overflow:coreneuron::nrnran123_deletestream(coreneuron::nrnran123_State*, bool) unsigned-integer-overflow:coreneuron::nrnran123_newstream3(unsigned int, unsigned int, unsigned int, bool) +unsigned-integer-overflow:Py_INCREF(_object*) vptr:NetCon::disconnect(ivObservable*) vptr:ObjObservable::object() vptr:PreSyn::disconnect(ivObservable*) \ No newline at end of file From 840a7a5c570951ec1c7e4e575ae190194fe012d8 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 6 May 2024 16:28:48 +0200 Subject: [PATCH 61/62] BBS: pickle is now a std::vector (#2822) --- src/nrniv/nrnpy.h | 7 +- src/nrnpython/nrnpy_p2h.cpp | 120 ++++++++++++++++------------------ src/parallel/bbs.cpp | 36 ++++------ src/parallel/bbs.h | 4 +- src/parallel/bbsclimpi.cpp | 19 +++--- src/parallel/bbsdirect.h | 8 ++- src/parallel/bbsdirectmpi.cpp | 21 +++--- src/parallel/bbsimpl.h | 19 +++--- src/parallel/bbslocal.cpp | 15 ++--- src/parallel/bbslocal.h | 6 +- src/parallel/bbslsrv.cpp | 11 ++-- src/parallel/bbslsrv.hpp | 4 +- src/parallel/bbsrcli.h | 6 +- src/parallel/ocbbs.cpp | 100 ++++++++++------------------ 14 files changed, 162 insertions(+), 214 deletions(-) diff --git a/src/nrniv/nrnpy.h b/src/nrniv/nrnpy.h index ce3cb89b83..d18fd9b7c6 100644 --- a/src/nrniv/nrnpy.h +++ b/src/nrniv/nrnpy.h @@ -1,5 +1,6 @@ #pragma once #include +#include /** * Declarations of global symbols in NEURON that have to be populated with python-version-specific * values when dynamic Python is enabled. These are set by the nrnpython_reg_real function, and @@ -24,7 +25,7 @@ namespace neuron::python { struct impl_ptrs { Object* (*callable_with_args)(Object*, int narg){}; double (*call_func)(Object*, int, int*){}; - char* (*call_picklef)(char*, std::size_t size, int narg, std::size_t* retsize){}; + std::vector (*call_picklef)(const std::vector&, int narg){}; void (*call_python_with_section)(Object*, Section*){}; void (*cmdtool)(Object*, int type, double x, double y, int kd){}; int (*guigetstr)(Object*, char**){}; @@ -43,9 +44,9 @@ struct impl_ptrs { Object* (*mpi_alltoall_type)(int, int){}; double (*object_to_double)(Object*){}; void* (*opaque_obj2pyobj)(Object*){}; - Object* (*pickle2po)(char*, std::size_t size){}; + Object* (*pickle2po)(const std::vector&){}; Object* (*po2ho)(PyObject*){}; - char* (*po2pickle)(Object*, std::size_t* size){}; + std::vector (*po2pickle)(Object*){}; double (*praxis_efun)(Object* pycallable, Object* hvec){}; int (*pysame)(Object* o1, Object* o2){}; void (*py2n_component)(Object*, Symbol*, int, int){}; diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 74a05c649b..2d0e214117 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -611,26 +611,26 @@ static PyObject* loads; static PyObject* dumps; static void setpickle() { - PyObject* pickle; - if (!dumps) { - pickle = PyImport_ImportModule("pickle"); - if (pickle) { - Py_INCREF(pickle); - dumps = PyObject_GetAttrString(pickle, "dumps"); - loads = PyObject_GetAttrString(pickle, "loads"); - if (dumps) { - Py_INCREF(dumps); - Py_INCREF(loads); - } - } - if (!dumps || !loads) { - hoc_execerror("Neither Python cPickle nor pickle are available", 0); + if (dumps) { + return; + } + PyObject* pickle = PyImport_ImportModule("pickle"); + if (pickle) { + Py_INCREF(pickle); + dumps = PyObject_GetAttrString(pickle, "dumps"); + loads = PyObject_GetAttrString(pickle, "loads"); + if (dumps) { + Py_INCREF(dumps); + Py_INCREF(loads); } } + if (!dumps || !loads) { + hoc_execerror("Neither Python cPickle nor pickle are available", 0); + } } // note that *size includes the null terminating character if it exists -static char* pickle(PyObject* p, size_t* size) { +static std::vector pickle(PyObject* p) { PyObject* arg = PyTuple_Pack(1, p); PyObject* r = nrnpy_pyCallObject(dumps, arg); Py_XDECREF(arg); @@ -639,29 +639,25 @@ static char* pickle(PyObject* p, size_t* size) { } assert(r); assert(PyBytes_Check(r)); - *size = PyBytes_Size(r); - char* buf1 = PyBytes_AsString(r); - char* buf = new char[*size]; - for (size_t i = 0; i < *size; ++i) { - buf[i] = buf1[i]; - } + std::size_t size = PyBytes_Size(r); + char* buf = PyBytes_AsString(r); + std::vector ret(buf, buf + size); Py_XDECREF(r); - return buf; + return ret; } -static char* po2pickle(Object* ho, std::size_t* size) { +static std::vector po2pickle(Object* ho) { setpickle(); if (ho && ho->ctemplate->sym == nrnpy_pyobj_sym_) { PyObject* po = nrnpy_hoc2pyobject(ho); - char* buf = pickle(po, size); - return buf; + return pickle(po); } else { - return 0; + return {}; } } -static PyObject* unpickle(char* s, size_t size) { - PyObject* ps = PyBytes_FromStringAndSize(s, size); +static PyObject* unpickle(const char* s, std::size_t len) { + PyObject* ps = PyBytes_FromStringAndSize(s, len); PyObject* arg = PyTuple_Pack(1, ps); PyObject* po = nrnpy_pyCallObject(loads, arg); assert(po); @@ -670,9 +666,13 @@ static PyObject* unpickle(char* s, size_t size) { return po; } -static Object* pickle2po(char* s, std::size_t size) { +static PyObject* unpickle(const std::vector& s) { + return unpickle(s.data(), s.size()); +} + +static Object* pickle2po(const std::vector& s) { setpickle(); - PyObject* po = unpickle(s, size); + PyObject* po = unpickle(s); Object* ho = nrnpy_pyobject_in_obj(po); Py_XDECREF(po); return ho; @@ -739,7 +739,7 @@ static char* nrnpyerr_str() { return NULL; } -char* call_picklef(char* fname, std::size_t size, int narg, std::size_t* retsize) { +std::vector call_picklef(const std::vector& fname, int narg) { // fname is a pickled callable, narg is the number of args on the // hoc stack with types double, char*, hoc Vector, and PythonObject // callable return must be pickleable. @@ -748,7 +748,7 @@ char* call_picklef(char* fname, std::size_t size, int narg, std::size_t* retsize PyObject* callable; setpickle(); - PyObject* ps = PyBytes_FromStringAndSize(fname, size); + PyObject* ps = PyBytes_FromStringAndSize(fname.data(), fname.size()); args = PyTuple_Pack(1, ps); callable = nrnpy_pyCallObject(loads, args); assert(callable); @@ -777,7 +777,7 @@ char* call_picklef(char* fname, std::size_t size, int narg, std::size_t* retsize PyErr_Print(); } } - char* rs = pickle(result, retsize); + auto rs = pickle(result); Py_XDECREF(result); return rs; } @@ -811,17 +811,15 @@ static PyObject* char2pylist(char* buf, int np, int* cnt, int* displ) { #if NRNMPI static PyObject* py_allgather(PyObject* psrc) { int np = nrnmpi_numprocs; - size_t sz; - char* sbuf = pickle(psrc, &sz); + auto sbuf = pickle(psrc); // what are the counts from each rank int* rcnt = new int[np]; - rcnt[nrnmpi_myid] = int(sz); + rcnt[nrnmpi_myid] = static_cast(sbuf.size()); nrnmpi_int_allgather_inplace(rcnt, 1); int* rdispl = mk_displ(rcnt); char* rbuf = new char[rdispl[np]]; - nrnmpi_char_allgatherv(sbuf, rbuf, rcnt, rdispl); - delete[] sbuf; + nrnmpi_char_allgatherv(sbuf.data(), rbuf, rcnt, rdispl); PyObject* pdest = char2pylist(rbuf, np, rcnt, rdispl); delete[] rbuf; @@ -832,10 +830,9 @@ static PyObject* py_allgather(PyObject* psrc) { static PyObject* py_gather(PyObject* psrc, int root) { int np = nrnmpi_numprocs; - size_t sz; - char* sbuf = pickle(psrc, &sz); + auto sbuf = pickle(psrc); // what are the counts from each rank - int scnt = int(sz); + int scnt = static_cast(sbuf.size()); int* rcnt = NULL; if (root == nrnmpi_myid) { rcnt = new int[np]; @@ -848,8 +845,7 @@ static PyObject* py_gather(PyObject* psrc, int root) { rbuf = new char[rdispl[np]]; } - nrnmpi_char_gatherv(sbuf, scnt, rbuf, rcnt, rdispl, root); - delete[] sbuf; + nrnmpi_char_gatherv(sbuf.data(), scnt, rbuf, rcnt, rdispl, root); PyObject* pdest = Py_None; if (root == nrnmpi_myid) { @@ -865,25 +861,23 @@ static PyObject* py_gather(PyObject* psrc, int root) { static PyObject* py_broadcast(PyObject* psrc, int root) { // Note: root returns reffed psrc. - char* buf = NULL; + std::vector buf{}; int cnt = 0; if (root == nrnmpi_myid) { - size_t sz; - buf = pickle(psrc, &sz); - cnt = int(sz); + buf = pickle(psrc); + cnt = static_cast(buf.size()); } nrnmpi_int_broadcast(&cnt, 1, root); if (root != nrnmpi_myid) { - buf = new char[cnt]; + buf.resize(cnt); } - nrnmpi_char_broadcast(buf, cnt, root); + nrnmpi_char_broadcast(buf.data(), cnt, root); PyObject* pdest = psrc; if (root != nrnmpi_myid) { - pdest = unpickle(buf, size_t(cnt)); + pdest = unpickle(buf); } else { Py_INCREF(pdest); } - delete[] buf; return pdest; } #endif @@ -1003,11 +997,10 @@ static Object* py_alltoall_type(int size, int type) { Py_DECREF(p); continue; } - size_t sz; - char* b = pickle(p, &sz); + auto b = pickle(p); if (size >= 0) { - if (curpos + sz >= bufsz) { - bufsz = bufsz * 2 + sz; + if (curpos + b.size() >= bufsz) { + bufsz = bufsz * 2 + b.size(); char* s2 = new char[bufsz]; for (size_t i = 0; i < curpos; ++i) { s2[i] = s[i]; @@ -1015,13 +1008,12 @@ static Object* py_alltoall_type(int size, int type) { delete[] s; s = s2; } - for (size_t j = 0; j < sz; ++j) { + for (size_t j = 0; j < b.size(); ++j) { s[curpos + j] = b[j]; } } - curpos += sz; - scnt[i] = sz; - delete[] b; + curpos += b.size(); + scnt[i] = static_cast(b.size()); Py_DECREF(p); } Py_DECREF(iterator); @@ -1048,7 +1040,6 @@ static Object* py_alltoall_type(int size, int type) { // exchange sdispl = mk_displ(scnt); rdispl = mk_displ(rcnt); - char* r = 0; if (size < 0) { pdest = PyTuple_New(2); PyTuple_SetItem(pdest, 0, Py_BuildValue("l", (long) sdispl[np])); @@ -1058,7 +1049,7 @@ static Object* py_alltoall_type(int size, int type) { delete[] rcnt; delete[] rdispl; } else { - r = new char[rdispl[np] + 1]; // force > 0 for all None case + char* r = new char[rdispl[np] + 1]; // force > 0 for all None case nrnmpi_char_alltoallv(s, scnt, sdispl, r, rcnt, rdispl); delete[] s; delete[] scnt; @@ -1076,13 +1067,13 @@ static Object* py_alltoall_type(int size, int type) { // destination counts rcnt = new int[1]; nrnmpi_int_scatter(scnt, rcnt, 1, root); - r = new char[rcnt[0] + 1]; // rcnt[0] can be 0 + std::vector r(rcnt[0] + 1); // rcnt[0] can be 0 // exchange if (nrnmpi_myid == root) { sdispl = mk_displ(scnt); } - nrnmpi_char_scatterv(s, scnt, sdispl, r, rcnt[0], root); + nrnmpi_char_scatterv(s, scnt, sdispl, r.data(), rcnt[0], root); if (s) delete[] s; if (scnt) @@ -1091,13 +1082,12 @@ static Object* py_alltoall_type(int size, int type) { delete[] sdispl; if (rcnt[0]) { - pdest = unpickle(r, size_t(rcnt[0])); + pdest = unpickle(r); } else { pdest = Py_None; Py_INCREF(pdest); } - delete[] r; delete[] rcnt; assert(rdispl == NULL); } diff --git a/src/parallel/bbs.cpp b/src/parallel/bbs.cpp index 2a51b20c55..c27d2286e3 100644 --- a/src/parallel/bbs.cpp +++ b/src/parallel/bbs.cpp @@ -87,20 +87,12 @@ BBSImpl::BBSImpl() { integ_time_ = 0.; working_id_ = 0; n_ = 0; - pickle_ret_ = 0; - pickle_ret_size_ = 0; } BBS::~BBS() { delete impl_; } -BBSImpl::~BBSImpl() { - if (pickle_ret_) { - delete[] pickle_ret_; - } -} - bool BBS::is_master() { return BBSImpl::is_master_; } @@ -179,10 +171,10 @@ char* BBS::upkstr() { return s; } -char* BBS::upkpickle(size_t* n) { - char* s = impl_->upkpickle(n); +std::vector BBS::upkpickle() { + auto s = impl_->upkpickle(); if (debug) { - printf("upkpickle %lu |%s|\n", *n, s); + printf("upkpickle %lu |%s|\n", s.size(), s.data()); } return s; } @@ -222,11 +214,11 @@ void BBS::pkstr(const char* s) { impl_->pkstr(s); } -void BBS::pkpickle(const char* s, size_t n) { +void BBS::pkpickle(const std::vector& s) { if (debug) { - printf("pkpickle %lu |%s|\n", n, s); + printf("pkpickle %lu |%s|\n", s.size(), s.data()); } - impl_->pkpickle(s, n); + impl_->pkpickle(s); } #if 0 @@ -270,9 +262,7 @@ void BBSImpl::execute(int id) { // assumes a "_todo" message in receive buffer ++etaskcnt; double st, et; int userid; - char* rs; char* s; - size_t n; int i; int save_id = working_id_; int save_n = n_; @@ -285,7 +275,7 @@ void BBSImpl::execute(int id) { // assumes a "_todo" message in receive buffer userid = upkint(); int wid = upkint(); hoc_ac_ = double(id); - rs = execute_helper(&n, id); // builds and execute hoc statement + auto rs = execute_helper(id); // builds and execute hoc statement et = time() - st; total_exec_time += et; if (debug) { @@ -294,12 +284,11 @@ void BBSImpl::execute(int id) { // assumes a "_todo" message in receive buffer pkbegin(); pkint(userid); pkint(wid); - pkint(rs ? 1 : 0); - if (!rs) { + pkint(!rs.empty() ? 1 : 0); + if (rs.empty()) { pkdouble(hoc_ac_); } else { - pkpickle(rs, n); - delete[] rs; + pkpickle(rs); } working_id_ = save_id; n_ = save_n; @@ -377,10 +366,7 @@ bool BBSImpl::working(int& id, double& x, int& userid) { } else { assert(rtype == 1); x = 0.0; - if (pickle_ret_) { - delete[] pickle_ret_; - } - pickle_ret_ = upkpickle(&pickle_ret_size_); + pickle_ret_ = upkpickle(); } --n_; if (debug) { diff --git a/src/parallel/bbs.h b/src/parallel/bbs.h index 01f4ed28d0..a4cd439502 100644 --- a/src/parallel/bbs.h +++ b/src/parallel/bbs.h @@ -19,7 +19,7 @@ class BBS { double upkdouble(); void upkvec(int n, double* px); // n input px space must exist char* upkstr(); // delete [] char* when finished - char* upkpickle(size_t* size); // delete [] char* when finished + std::vector upkpickle(); // before posting use these void pkbegin(); @@ -27,7 +27,7 @@ class BBS { void pkdouble(double); void pkvec(int n, double* px); // doesn't pack n void pkstr(const char*); - void pkpickle(const char*, size_t size); + void pkpickle(const std::vector&); void post(const char*); int submit(int userid); diff --git a/src/parallel/bbsclimpi.cpp b/src/parallel/bbsclimpi.cpp index 101949cd83..340b8cb3bc 100644 --- a/src/parallel/bbsclimpi.cpp +++ b/src/parallel/bbsclimpi.cpp @@ -72,8 +72,12 @@ char* BBSClient::upkstr() { return nrnmpi_upkstr(recvbuf_); // do not forget to free(string) } -char* BBSClient::upkpickle(size_t* n) { - return nrnmpi_upkpickle(n, recvbuf_); // do not forget to free(string) +std::vector BBSClient::upkpickle() { + std::size_t len{}; + char* s = nrnmpi_upkpickle(&len, recvbuf_); + std::vector ret(s, s + len); + delete[] s; + return ret; } void BBSClient::pkbegin() { @@ -100,8 +104,8 @@ void BBSClient::pkstr(const char* s) { nrnmpi_pkstr(s, sendbuf_); } -void BBSClient::pkpickle(const char* s, size_t n) { - nrnmpi_pkpickle(s, n, sendbuf_); +void BBSClient::pkpickle(const std::vector& s) { + nrnmpi_pkpickle(s.data(), s.size(), sendbuf_); } void BBSClient::post(const char* key) { @@ -222,8 +226,6 @@ int BBSClient::look_take_todo() { int BBSClient::take_todo() { int type; - char* rs; - size_t n; while ((type = get(0, TAKE_TODO)) == CONTEXT) { upkbegin(); upkint(); // throw away userid @@ -232,10 +234,7 @@ int BBSClient::take_todo() { printf("%d execute context\n", nrnmpi_myid_bbs); fflush(stdout); #endif - rs = execute_helper(&n, -1); - if (rs) { - delete[] rs; - } + execute_helper(-1); } upkbegin(); return type; diff --git a/src/parallel/bbsdirect.h b/src/parallel/bbsdirect.h index 9c595b710d..f3b22b62f9 100644 --- a/src/parallel/bbsdirect.h +++ b/src/parallel/bbsdirect.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include "bbsimpl.h" @@ -25,8 +27,8 @@ class BBSDirect: public BBSImpl { int upkint() override; double upkdouble() override; void upkvec(int, double*) override; - char* upkstr() override; // delete [] char* when finished - char* upkpickle(size_t*) override; // delete [] char* when finished + char* upkstr() override; // delete [] char* when finished + std::vector upkpickle() override; // before posting use these void pkbegin() override; @@ -34,7 +36,7 @@ class BBSDirect: public BBSImpl { void pkdouble(double) override; void pkvec(int, double*) override; void pkstr(const char*) override; - void pkpickle(const char*, size_t) override; + void pkpickle(const std::vector&) override; void post(const char*) override; void post_todo(int parentid) override; diff --git a/src/parallel/bbsdirectmpi.cpp b/src/parallel/bbsdirectmpi.cpp index ca68f86dfc..1ba9e6d7ce 100644 --- a/src/parallel/bbsdirectmpi.cpp +++ b/src/parallel/bbsdirectmpi.cpp @@ -50,7 +50,6 @@ void BBSDirect::context() { // then id > 0 need to execute the context statement // but id == 0 does not. if (nrnmpi_numprocs > 1 && nrnmpi_numprocs_bbs < nrnmpi_numprocs_world) { - size_t n; bbsmpibuf* rsav = recvbuf_; // May naturally be NULL anyway recvbuf_ = nrnmpi_newbuf(sendbuf_->size); nrnmpi_ref(recvbuf_); @@ -58,7 +57,7 @@ void BBSDirect::context() { nrnmpi_upkbegin(recvbuf_); nrnmpi_upkint(recvbuf_); nrnmpi_upkint(recvbuf_); // slot reserved for tag - execute_helper(&n, -1, false); + execute_helper(-1, false); nrnmpi_unref(recvbuf_); recvbuf_ = rsav; } @@ -98,13 +97,15 @@ char* BBSDirect::upkstr() { return s; } -char* BBSDirect::upkpickle(size_t* n) { - char* s; - s = nrnmpi_upkpickle(n, recvbuf_); +std::vector BBSDirect::upkpickle() { + std::size_t n; + char* s = nrnmpi_upkpickle(&n, recvbuf_); #if debug - printf("upkpickle returning %d bytes\n", *n); + printf("upkpickle returning %d bytes\n", n); #endif - return s; + std::vector ret(s, s + n); + delete[] s; + return ret; } void BBSDirect::pkbegin() { @@ -145,11 +146,11 @@ void BBSDirect::pkstr(const char* s) { nrnmpi_pkstr(s, sendbuf_); } -void BBSDirect::pkpickle(const char* s, size_t n) { +void BBSDirect::pkpickle(const std::vector& s) { #if debug - printf("%d BBSDirect::pkpickle %d bytes\n", nrnmpi_myid_bbs, n); + printf("%d BBSDirect::pkpickle %d bytes\n", nrnmpi_myid_bbs, s.size()); #endif - nrnmpi_pkpickle(s, n, sendbuf_); + nrnmpi_pkpickle(s.data(), s.size(), sendbuf_); } void BBSDirect::post(const char* key) { diff --git a/src/parallel/bbsimpl.h b/src/parallel/bbsimpl.h index 6a89af82ed..92a94b07e2 100644 --- a/src/parallel/bbsimpl.h +++ b/src/parallel/bbsimpl.h @@ -1,9 +1,11 @@ #pragma once +#include + class BBSImpl { public: BBSImpl(); - virtual ~BBSImpl(); + virtual ~BBSImpl() = default; virtual bool look(const char*) = 0; @@ -13,8 +15,8 @@ class BBSImpl { virtual int upkint() = 0; virtual double upkdouble() = 0; virtual void upkvec(int, double*) = 0; - virtual char* upkstr() = 0; // delete [] char* when finished - virtual char* upkpickle(size_t*) = 0; // delete [] char* when finished + virtual char* upkstr() = 0; // delete [] char* when finished + virtual std::vector upkpickle() = 0; // before posting use these virtual void pkbegin() = 0; @@ -22,7 +24,7 @@ class BBSImpl { virtual void pkdouble(double) = 0; virtual void pkvec(int, double*) = 0; virtual void pkstr(const char*) = 0; - virtual void pkpickle(const char*, size_t) = 0; + virtual void pkpickle(const std::vector&) = 0; virtual void post(const char*) = 0; virtual void post_todo(int parentid) = 0; @@ -54,8 +56,7 @@ class BBSImpl { double wait_time_; double integ_time_; double send_time_; - char* pickle_ret_; - size_t pickle_ret_size_; + std::vector pickle_ret_; static bool is_master_; static bool started_, done_; static int mytid_; @@ -63,9 +64,9 @@ class BBSImpl { static bool master_works_; protected: - char* execute_helper(size_t*, int id, bool exec = true); // involves hoc specific details in - // ocbbs.cpp - void subworld_worker_execute(); // shadows execute_helper. ie. each of + std::vector execute_helper(int id, bool exec = true); // involves hoc specific details in + // ocbbs.cpp + void subworld_worker_execute(); // shadows execute_helper. ie. each of // the nrnmpi_myid_bbs workers (and master) need to execute // the same thing on each of the subworld processes // associated with nrnmpi_myid==0. A subworld does not diff --git a/src/parallel/bbslocal.cpp b/src/parallel/bbslocal.cpp index 32549658a0..7c12639bcb 100644 --- a/src/parallel/bbslocal.cpp +++ b/src/parallel/bbslocal.cpp @@ -70,17 +70,16 @@ char* BBSLocal::upkstr() { return s; } -char* BBSLocal::upkpickle(size_t* n) { +std::vector BBSLocal::upkpickle() { int len{}; - char* s; if (!taking_ || taking_->upkint(&len)) { perror("upkpickle length"); } - s = new char[len]; - if (taking_->upkpickle(s, n)) { + std::vector s{}; + if (taking_->upkpickle(s)) { perror("upkpickle data"); } - assert(*n == len); + assert(s.size() == len); return s; } @@ -117,11 +116,11 @@ void BBSLocal::pkstr(const char* s) { } } -void BBSLocal::pkpickle(const char* s, size_t n) { - if (!posting_ || posting_->pkint(n)) { +void BBSLocal::pkpickle(const std::vector& s) { + if (!posting_ || posting_->pkint(s.size())) { perror("pkpickle size"); } - if (!posting_ || posting_->pkpickle(s, n)) { + if (!posting_ || posting_->pkpickle(s)) { perror("pkpickle data"); } } diff --git a/src/parallel/bbslocal.h b/src/parallel/bbslocal.h index dba6051a23..0480f60679 100644 --- a/src/parallel/bbslocal.h +++ b/src/parallel/bbslocal.h @@ -17,8 +17,8 @@ class BBSLocal: public BBSImpl { int upkint() override; double upkdouble() override; void upkvec(int, double*) override; - char* upkstr() override; // delete [] char* when finished - char* upkpickle(size_t* size) override; // delete [] char* when finished + char* upkstr() override; // delete [] char* when finished + std::vector upkpickle() override; // before posting use these void pkbegin() override; @@ -26,7 +26,7 @@ class BBSLocal: public BBSImpl { void pkdouble(double) override; void pkvec(int, double*) override; void pkstr(const char*) override; - void pkpickle(const char*, size_t) override; + void pkpickle(const std::vector&) override; void post(const char*) override; void post_todo(int parentid) override; diff --git a/src/parallel/bbslsrv.cpp b/src/parallel/bbslsrv.cpp index 5d0a1c4f33..1d6092508c 100644 --- a/src/parallel/bbslsrv.cpp +++ b/src/parallel/bbslsrv.cpp @@ -108,8 +108,8 @@ int MessageValue::pkstr(const char* str) { return 0; } -int MessageValue::pkpickle(const char* bytes, size_t n) { - args_.emplace_back(std::vector(bytes, bytes + n)); +int MessageValue::pkpickle(const std::vector& s) { + args_.emplace_back(std::vector(s)); return 0; } @@ -160,13 +160,10 @@ int MessageValue::upkstr(char* s) { return -1; } -int MessageValue::upkpickle(char* s, size_t* n) { +int MessageValue::upkpickle(std::vector& s) { const auto& mi = args_.front(); if (const auto* val = std::get_if>(args_.data() + index_)) { - *n = val->size(); - for (std::size_t i = 0; i < *n; ++i) { - s[i] = val->at(i); - } + s = *val; ++index_; return 0; } diff --git a/src/parallel/bbslsrv.hpp b/src/parallel/bbslsrv.hpp index ed6f87e68a..61c247d6f3 100644 --- a/src/parallel/bbslsrv.hpp +++ b/src/parallel/bbslsrv.hpp @@ -21,13 +21,13 @@ class MessageValue: public Resource { int upkdouble(double*); int upkvec(int, double*); int upkstr(char*); - int upkpickle(char*, size_t*); + int upkpickle(std::vector&); int pkint(int); int pkdouble(double); int pkvec(int, double*); int pkstr(const char*); - int pkpickle(const char*, size_t); + int pkpickle(const std::vector&); private: std::vector args_{}; diff --git a/src/parallel/bbsrcli.h b/src/parallel/bbsrcli.h index 72ef12a9ab..160555c385 100644 --- a/src/parallel/bbsrcli.h +++ b/src/parallel/bbsrcli.h @@ -18,8 +18,8 @@ class BBSClient: public BBSImpl { // implemented as PVM Client int upkint() override; double upkdouble() override; void upkvec(int, double*) override; - char* upkstr() override; // delete [] char* when finished - char* upkpickle(size_t*) override; // delete [] char* when finished + char* upkstr() override; // delete [] char* when finished + std::vector upkpickle() override; // before posting use these void pkbegin() override; @@ -27,7 +27,7 @@ class BBSClient: public BBSImpl { // implemented as PVM Client void pkdouble(double) override; void pkvec(int, double*) override; void pkstr(const char*) override; - void pkpickle(const char*, size_t) override; + void pkpickle(const std::vector&) override; void post(const char*) override; void post_todo(int parentid) override; diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 9f59ad7c5c..ca627c1a80 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -104,7 +104,6 @@ void bbs_done() { static int submit_help(OcBBS* bbs) { int id, i, firstarg, style; - char* pname = 0; // if using Python callable posting_ = true; bbs->pkbegin(); i = 1; @@ -124,15 +123,14 @@ static int submit_help(OcBBS* bbs) { bbs->pkstr(gargstr(i++)); } else { Object* ob = *hoc_objgetarg(i++); - size_t size; + std::vector pname{}; if (neuron::python::methods.po2pickle) { - pname = neuron::python::methods.po2pickle(ob, &size); + pname = neuron::python::methods.po2pickle(ob); } - if (pname) { + if (!pname.empty()) { style = 3; bbs->pkint(style); // pyfun, arg1, ... style - bbs->pkpickle(pname, size); - delete[] pname; + bbs->pkpickle(pname); } else { style = 2; bbs->pkint(style); // [object],"fname", arg1, ... style @@ -164,12 +162,10 @@ static int submit_help(OcBBS* bbs) { bbs->pkint(0); // hoc statement style bbs->pkstr(gargstr(i)); } else if (neuron::python::methods.po2pickle) { - size_t size; - pname = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); + auto pname = neuron::python::methods.po2pickle(*hoc_objgetarg(i)); bbs->pkint(3); // pyfun with no arg style - bbs->pkpickle(pname, size); + bbs->pkpickle(pname); bbs->pkint(0); // argtypes - delete[] pname; } } posting_ = false; @@ -287,10 +283,8 @@ static void pack_help(int i, OcBBS* bbs) { bbs->pkint(n); bbs->pkvec(n, px); } else { // must be a PythonObject - size_t size; - char* s = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); - bbs->pkpickle(s, size); - delete[] s; + auto s = neuron::python::methods.po2pickle(*hoc_objgetarg(i)); + bbs->pkpickle(s); } } } @@ -372,11 +366,9 @@ static Object** upkvec(void* v) { static Object** upkpyobj(void* v) { OcBBS* bbs = (OcBBS*) v; - size_t n; - char* s = bbs->upkpickle(&n); + std::vector s = bbs->upkpickle(); assert(neuron::python::methods.pickle2po); - Object* po = neuron::python::methods.pickle2po(s, n); - delete[] s; + Object* po = neuron::python::methods.pickle2po(s); return hoc_temp_objptr(po); } @@ -385,12 +377,9 @@ static Object** pyret(void* v) { return bbs->pyret(); } Object** BBS::pyret() { - assert(impl_->pickle_ret_); assert(neuron::python::methods.pickle2po); - Object* po = neuron::python::methods.pickle2po(impl_->pickle_ret_, impl_->pickle_ret_size_); - delete[] impl_->pickle_ret_; - impl_->pickle_ret_ = 0; - impl_->pickle_ret_size_ = 0; + Object* po = neuron::python::methods.pickle2po(impl_->pickle_ret_); + impl_->pickle_ret_.clear(); return hoc_temp_objptr(po); } @@ -1191,8 +1180,7 @@ void ParallelContext_reg() { // A python pickle (https://docs.python.org/3/library/pickle.html) followed by arguments. // Return a string that is of size `size`. // Dry run if `exec` is false. -char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { - char* python_pickle; // Used only for style == 3 +std::vector BBSImpl::execute_helper(int id, bool exec) { int subworld = (nrnmpi_numprocs > 1 && nrnmpi_numprocs_bbs < nrnmpi_numprocs_world); int style = upkint(); if (subworld) { @@ -1202,8 +1190,7 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { info[1] = style; nrnmpi_int_broadcast(info, 2, 0); } - char* rs = nullptr; - *size = 0; + std::vector rs{}; switch (style) { case 0: { char* statement = upkstr(); @@ -1216,7 +1203,7 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { delete[] statement; } break; default: { - size_t npickle; + std::vector python_pickle{}; // Only for style == 3 Symbol* fname = nullptr; Object* ob = nullptr; std::list sarg; // Store the strings pointer to delete[] them later @@ -1261,11 +1248,11 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { hoc_execerror("with subworlds, this submit style not implemented", nullptr); } } else if (style == 3) { // Python callable - python_pickle = upkpickle(&npickle); + python_pickle = upkpickle(); if (subworld) { - int size = npickle; + int size = static_cast(python_pickle.size()); nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(python_pickle, size, 0); + nrnmpi_char_broadcast(python_pickle.data(), size, 0); } } else { char* fname_str = upkstr(); @@ -1315,31 +1302,23 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { } hoc_pushobj(vec->temp_objvar()); } else { // PythonObject - size_t n; - char* pickle = upkpickle(&n); - int size = n; + auto s = upkpickle(); + int size = static_cast(s.size()); if (subworld) { nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(pickle, size, 0); + nrnmpi_char_broadcast(s.data(), size, 0); } assert(neuron::python::methods.pickle2po); - Object* po = neuron::python::methods.pickle2po(pickle, n); - delete[] pickle; + Object* po = neuron::python::methods.pickle2po(s); hoc_pushobj(hoc_temp_objptr(po)); } } if (style == 3) { assert(neuron::python::methods.call_picklef); - if (pickle_ret_) { - delete[] pickle_ret_; - pickle_ret_ = nullptr; - pickle_ret_size_ = 0; - } if (exec) { - rs = neuron::python::methods.call_picklef(python_pickle, npickle, narg, size); + rs = neuron::python::methods.call_picklef(python_pickle, narg); } hoc_ac_ = 0.; - delete[] python_pickle; } else { hoc_ac_ = 0.; if (exec) { @@ -1388,7 +1367,7 @@ void BBSImpl::subworld_worker_execute() { } int i, j; int npickle; - char* s; + std::vector s{}; Symbol* fname = 0; Object* ob = nullptr; char* sarg[20]; // up to 20 arguments may be strings @@ -1397,15 +1376,15 @@ void BBSImpl::subworld_worker_execute() { if (style == 3) { // python callable nrnmpi_int_broadcast(&npickle, 1, 0); - s = new char[npickle]; - nrnmpi_char_broadcast(s, npickle, 0); + s.resize(npickle); + nrnmpi_char_broadcast(s.data(), npickle, 0); } else if (style == 1) { // hoc function int size; nrnmpi_int_broadcast(&size, 1, 0); // includes terminator // printf("%d subworld hoc function string size = %d\n", nrnmpi_myid_world, size); - s = new char[size]; - nrnmpi_char_broadcast(s, size, 0); - fname = hoc_lookup(s); + s.resize(size); + nrnmpi_char_broadcast(s.data(), size, 0); + fname = hoc_lookup(s.data()); if (!fname) { return; } // error raised by sender @@ -1440,26 +1419,21 @@ void BBSImpl::subworld_worker_execute() { } else { // PythonObject int n; nrnmpi_int_broadcast(&n, 1, 0); - char* s; - s = new char[n]; - nrnmpi_char_broadcast(s, n, 0); - Object* po = neuron::python::methods.pickle2po(s, size_t(n)); - delete[] s; + std::vector s(n); + nrnmpi_char_broadcast(s.data(), n, 0); + Object* po = neuron::python::methods.pickle2po(s); hoc_pushobj(hoc_temp_objptr(po)); } } if (style == 3) { - size_t size; - char* rs = neuron::python::methods.call_picklef(s, size_t(npickle), narg, &size); - assert(rs); - delete[] rs; + auto rs = neuron::python::methods.call_picklef(s, narg); + assert(!rs.empty()); } else { // printf("%d subworld hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, narg); hoc_call_objfunc(fname, narg, ob); // printf("%d subworld return from hoc call %s\n", nrnmpi_myid_world, fname->name); } - delete[] s; for (i = 0; i < ns; ++i) { delete[] sarg[i]; } @@ -1496,10 +1470,8 @@ void BBSImpl::return_args(int id) { delete[] s; break; case 3: - size_t n; - s = upkpickle(&n); // pickled callable - i = upkint(); // arg manifest - delete[] s; + auto pickle = upkpickle(); // pickled callable + i = upkint(); // arg manifest break; } // now only args are left and ready to unpack. From d99cbb532907b4b3b08de7aaf0102cbbcce927c5 Mon Sep 17 00:00:00 2001 From: rgourdine <88497408+rgourdine@users.noreply.github.com> Date: Mon, 6 May 2024 14:11:55 -0400 Subject: [PATCH 62/62] change volume method (#2781) --- share/lib/python/neuron/rxd/region.py | 20 ++++++++++++++++++-- share/lib/python/neuron/rxd/rxd.py | 26 ++++++++++++++------------ test/rxd/test_region_volume.py | 20 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 test/rxd/test_region_volume.py diff --git a/share/lib/python/neuron/rxd/region.py b/share/lib/python/neuron/rxd/region.py index b3e1460a21..e2c6b608f8 100644 --- a/share/lib/python/neuron/rxd/region.py +++ b/share/lib/python/neuron/rxd/region.py @@ -344,8 +344,14 @@ def __repr__(self): def _short_repr(self): return "Extracellular" - def volume(self, index): + def volume(self, index=None): """Returns the volume of the voxel at a given index""" + if index is None: + if numpy.isscalar(self.alpha): + vol = self._nx * self._ny * self._nz * numpy.prod(self._dx) * self.alpha + else: + vol = numpy.sum(self.alpha) * numpy.prod(self._dx) + return vol if numpy.isscalar(self.alpha): return numpy.prod(self._dx) * self.alpha return numpy.prod(self._dx) * self.alpha[index] @@ -1000,6 +1006,16 @@ def secs(self, value): else: raise RxDException("Cannot set secs now; model already instantiated") - def volume(self, index): + def volume(self, index=None): """Returns the volume of the voxel at a given index""" + initializer._do_init() + if index is None: + vol = 0 + if hasattr(self, "_vol") and any(self._secs3d): + vol += numpy.sum(self._vol) + if hasattr(self, "_geometry") and any(self._secs1d): + vol += numpy.sum( + [self._geometry.volumes1d(sec) for sec in self._secs1d] + ) + return vol return self._vol[index] diff --git a/share/lib/python/neuron/rxd/rxd.py b/share/lib/python/neuron/rxd/rxd.py index e5f62e8a51..0ac5249684 100644 --- a/share/lib/python/neuron/rxd/rxd.py +++ b/share/lib/python/neuron/rxd/rxd.py @@ -905,6 +905,7 @@ def _setup_matrices(): num_3d_indices_per_1d_seg = numpy.asarray( num_3d_indices_per_1d_seg, dtype=numpy.int64 ) + hybrid_grid_ids.append(-1) hybrid_grid_ids = numpy.asarray(hybrid_grid_ids, dtype=numpy.int64) hybrid_indices3d = numpy.asarray(hybrid_indices3d, dtype=numpy.int64) @@ -912,18 +913,19 @@ def _setup_matrices(): volumes1d = numpy.asarray(volumes1d, dtype=float) volumes3d = numpy.asarray(volumes3d, dtype=float) dxs = numpy.asarray(grids_dx, dtype=float) - set_hybrid_data( - num_1d_indices_per_grid, - num_3d_indices_per_grid, - hybrid_indices1d, - hybrid_indices3d, - num_3d_indices_per_1d_seg, - hybrid_grid_ids, - rates, - volumes1d, - volumes3d, - dxs, - ) + if hybrid_grid_ids.size > 1: + set_hybrid_data( + num_1d_indices_per_grid, + num_3d_indices_per_grid, + hybrid_indices1d, + hybrid_indices3d, + num_3d_indices_per_1d_seg, + hybrid_grid_ids, + rates, + volumes1d, + volumes3d, + dxs, + ) # TODO: Replace this this to handle 1d/3d hybrid models """ diff --git a/test/rxd/test_region_volume.py b/test/rxd/test_region_volume.py new file mode 100644 index 0000000000..2575faa783 --- /dev/null +++ b/test/rxd/test_region_volume.py @@ -0,0 +1,20 @@ +def test_region_volume(neuron_nosave_instance): + h, rxd, _ = neuron_nosave_instance + dend1 = h.Section("dend1") + dend2 = h.Section("dend2") + diff = 1e-10 + dend1.nseg = 4 + dend2.nseg = 4 + cyt1 = rxd.Region(dend1.wholetree(), "i", dx=0.25) + cyt2 = rxd.Region(dend2.wholetree(), "i", dx=0.25) + ca1 = rxd.Species(cyt1, name="ca1", charge=2, initial=1e-12) + ca2 = rxd.Species(cyt2, name="ca2", charge=2, initial=1e-12) + dend1.L = 10 + dend1.diam = 2 + dend2.L = 10 + dend2.diam = 2 + rxd.set_solve_type(domain=[dend1], dimension=1) + rxd.set_solve_type(domain=[dend2], dimension=3) + h.finitialize() + assert abs(cyt1.volume() - sum(ca1.nodes(cyt1).volume)) < diff + assert abs(cyt2.volume() - sum(ca2.nodes(cyt2).volume)) < diff