diff --git a/CMakeLists.txt b/CMakeLists.txt index ec4701030e..ff3ac2e4c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,8 +89,6 @@ option(NRN_AVOID_ABSOLUTE_PATHS "Avoid embedding absolute paths in generated code (ccache optimisation)" ${NRN_AVOID_ABSOLUTE_PATHS_DEFAULT}) mark_as_advanced(NRN_AVOID_ABSOLUTE_PATHS) -option(NRN_DYNAMIC_UNITS_USE_LEGACY "Use legacy units as default for dynamic units" - ${NRN_DYNAMIC_UNITS_USE_LEGACY_DEFAULT}) # note that if CoreNEURON is enabled then it is not necessary to enable this option option(NRN_ENABLE_MOD_COMPATIBILITY "Enable CoreNEURON compatibility for MOD files" ${NRN_ENABLE_MOD_COMPATIBILITY_DEFAULT}) @@ -499,9 +497,6 @@ if(NRN_ENABLE_CORENEURON) set(CORENRN_ENABLE_UNIT_TESTS ${NRN_ENABLE_TESTS} CACHE BOOL "" FORCE) - set(CORENRN_ENABLE_LEGACY_UNITS - ${NRN_DYNAMIC_UNITS_USE_LEGACY} - CACHE BOOL "" FORCE) if(NRN_ENABLE_PROFILING) if(NRN_PROFILER STREQUAL "caliper") set(CORENRN_ENABLE_CALIPER_PROFILING ON) @@ -960,11 +955,6 @@ message(STATUS "CXX COMPILER | ${CMAKE_CXX_COMPILER}") message(STATUS "BUILD_TYPE | ${CMAKE_BUILD_TYPE} (allowed: ${allowableBuildTypes})") message(STATUS "COMPILE FLAGS | ${COMPILER_FLAGS}") message(STATUS "Shared | ${NRN_ENABLE_SHARED}") -if(NRN_DYNAMIC_UNITS_USE_LEGACY) - message(STATUS "Default units | legacy units") -else() - message(STATUS "Default units | modern units (2019 nist constants)") -endif() message(STATUS "MPI | ${NRN_ENABLE_MPI}") if(NRN_ENABLE_MPI) message(STATUS " DYNAMIC | ${NRN_ENABLE_MPI_DYNAMIC}") @@ -1035,9 +1025,6 @@ message(STATUS "CoreNEURON | ${NRN_ENABLE_CORENEURON}") if(NRN_ENABLE_CORENEURON) message(STATUS " PATH | ${CORENEURON_DIR}") message(STATUS " LINK FLAGS | ${CORENRN_LIB_LINK_FLAGS}") - if(NOT coreneuron_FOUND) - message(STATUS " Legacy Units| ${CORENRN_ENABLE_LEGACY_UNITS}") - endif() endif() if(NRN_UNIVERSAL2_BUILD) message(STATUS "CMAKE_OSX_ARCH| ${CMAKE_OSX_ARCHITECTURES}") diff --git a/cmake/BuildOptionDefaults.cmake b/cmake/BuildOptionDefaults.cmake index f0a55aaa6c..d52b65acd8 100644 --- a/cmake/BuildOptionDefaults.cmake +++ b/cmake/BuildOptionDefaults.cmake @@ -26,7 +26,6 @@ set(NRN_ENABLE_MPI_DYNAMIC_DEFAULT OFF) set(NRN_ENABLE_MOD_COMPATIBILITY_DEFAULT OFF) set(NRN_ENABLE_REL_RPATH_DEFAULT OFF) set(NRN_AVOID_ABSOLUTE_PATHS_DEFAULT OFF) -set(NRN_DYNAMIC_UNITS_USE_LEGACY_DEFAULT OFF) set(NRN_NMODL_CXX_FLAGS_DEFAULT "-O0") set(NRN_SANITIZERS_DEFAULT "") @@ -68,7 +67,6 @@ set(NRN_OPTION_NAME_LIST NRN_MODULE_INSTALL_OPTIONS NRN_PYTHON_DYNAMIC NRN_MPI_DYNAMIC - NRN_DYNAMIC_UNITS_USE_LEGACY NRN_RX3D_OPT_LEVEL NRN_SANITIZERS CMAKE_BUILD_TYPE diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index d11da0cbef..668ea44548 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -92,24 +92,6 @@ else() set(DISCRETE_EVENT_OBSERVER 0) endif() -# No longer a user option. Default modern units. Controlled at launch by the environment variable -# NRNUNIT_USE_LEGACY, and dynamically after launch by h.nrnunit_use_legacy(0or1). Left here solely -# to obtain a nrnunits.lib file for modlunit. Nmodl uses the nrnunits.lib.in file. -set(NRN_ENABLE_LEGACY_FR 0) -if(NRN_ENABLE_LEGACY_FR) - set(LegacyFR 1) - set(LegacyY "") - set(LegacyN "/") - set(LegacyYPy "") - set(LegacyNPy "#") -else() - set(LegacyFR 0) - set(LegacyY "/") - set(LegacyN "") - set(LegacyYPy "#") - set(LegacyNPy "") -endif() - if(NRN_ENABLE_MECH_DLL_STYLE) set(NRNMECH_DLL_STYLE 1) else() @@ -126,12 +108,6 @@ if(NRN_ENABLE_PYTHON_DYNAMIC) list(APPEND NRN_COMPILE_DEFS NRNPYTHON_DYNAMICLOAD) endif() -if(NRN_DYNAMIC_UNITS_USE_LEGACY) - set(DYNAMIC_UNITS_USE_LEGACY_DEFAULT 1) -else() - unset(DYNAMIC_UNITS_USE_LEGACY_DEFAULT) -endif() - # ============================================================================= # Dependencies option # ============================================================================= @@ -219,10 +195,8 @@ 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(nrnunits.lib share/nrn/lib nrnunits.lib share/lib) nrn_configure_dest_src(nrn.defaults share/nrn/lib nrn.defaults share/lib) -# NRN_DYNAMIC_UNITS requires nrnunits.lib.in be in same places as nrnunits.lib -file(COPY ${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib.in +file(COPY ${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib DESTINATION ${PROJECT_BINARY_DIR}/share/nrn/lib) if(NRN_MACOS_BUILD) @@ -241,8 +215,6 @@ if(MINGW) set(nrnskip_rebase "#") nrn_configure_file(mknrndll.mak src/mswin/lib) endif() -# TODO temporary workaround for mingw -file(COPY ${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib.in DESTINATION ${PROJECT_BINARY_DIR}/lib) # ============================================================================= # If Interviews is not provided, configure local files diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 6318ff8b7a..c70ddbfa85 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -91,9 +91,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* 1 for legacy, undef for NIST (as of 2017), for FARADAY and R */ -#undef LegacyFR - /* define if using mingw */ #undef MINGW diff --git a/docs/cmake_doc/options.rst b/docs/cmake_doc/options.rst index 2a28c84348..7dca20f1e9 100644 --- a/docs/cmake_doc/options.rst +++ b/docs/cmake_doc/options.rst @@ -597,20 +597,6 @@ NRN_ENABLE_DISCRETE_EVENT_OBSERVER:BOOL=ON Enable Observer to be a subclass of DiscreteEvent Can save space but a lot of component destruction may not notify other components that are watching it to no longer use that component. Useful only if one builds a model without needing to eliminate pieces of the model. -NRN_DYNAMIC_UNITS_USE_LEGACY:BOOL=OFF ----------------------------- - Default is to use modern faraday, R, etc. from 2019 nist constants. - When Off or ON, and in the absence of the ``NRNUNIT_USE_LEGACY=0or1`` - environment variable, the default dynamic value of ``h.nrnunit_use_legacy()`` - will be 0 or 1 respectively. - - At launch time (or import neuron), - use of legacy or modern units can be specified with the - ``NRNUNIT_USE_LEGACY=0or1`` environment variable. The use of legacy or - modern units can be dynamically specified after launch with the - ``h.nrnunit_use_legacy(0or1)`` function (with no args, returns the - current use flag). - NRN_ENABLE_MECH_DLL_STYLE:BOOL=ON --------------------------------- Dynamically load nrnmech shared library diff --git a/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst b/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst index 0a58b9a3e4..67010c3a56 100644 --- a/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst +++ b/docs/hoc/modelspec/programmatic/mechanisms/nmodl.rst @@ -285,12 +285,7 @@ Description: the UNIX units database. This can increase legibility and convenience, and is helpful both as a reminder to the user and as a means for automating the process of checking for consistency of units. - The UNIX units database taken into account is defined in the `nrnunits.lib file `_. - This file includes two versions of the units due to the updates in the values of their base - units. Currently there are legacy and modern units that contain the changes after the updates - introduced on 2019 to the nist constants. The selection between those two versions can be done - using the ``NRN_DYNAMIC_UNITS_USE_LEGACY`` CMake variable or a call to - ``h.nrnunit_use_legacy(bool)`` during runtime. + The UNIX units database (based on the 2019 updated NIST constants) taken into account is defined in the `nrnunits.lib file `_. New units can be defined in terms of default units and previously defined units by placing definitions in the UNITS block. e.g. diff --git a/docs/python/envvariables.rst b/docs/python/envvariables.rst index ac07a04c05..aa48b9dbc4 100644 --- a/docs/python/envvariables.rst +++ b/docs/python/envvariables.rst @@ -61,26 +61,3 @@ NEURON_MODULE_OPTIONS os.environ["NEURON_MODULE_OPTIONS"] = nrn_options from neuron import h assert(nrn_options in h.nrnversion(7)) - - - -NRNUNIT_USE_LEGACY ------------------- - When set to 1, legacy unit values for FARADAY, R, and a few other constants - are used. See ``nrn/share/lib/nrnunits.lib.in`` lines which begin with - ``@LegacyY@``, ``nrn/src/oc/hoc_init.c`` in the code section - ``static struct { /* Modern, Legacy units constants */``, and - ``nrn/src/nrnoc/eion.c``. - - When set to 0, (default), values from codata2018 are used. - See ``nrn/share/lib/nrnunits.lib.in`` lines that begin with - ``@LegacyN@`` and ``nrn/src/oc/nrnunits_modern.h``. - - Switching between legacy and modern units can also be done after launch - with the top level HOC function :func:`nrnunit_use_legacy`. - - The purpose of allowing legacy unit values is to easily validate - results of old models (double precision identity). - - This environment variable takes precedence over the CMake option - ``NRN_DYNAMIC_UNITS_USE_LEGACY``. diff --git a/docs/python/modelspec/programmatic/mechanisms/nmodl.rst b/docs/python/modelspec/programmatic/mechanisms/nmodl.rst index 6b7b1e60d2..afc456ab39 100755 --- a/docs/python/modelspec/programmatic/mechanisms/nmodl.rst +++ b/docs/python/modelspec/programmatic/mechanisms/nmodl.rst @@ -283,12 +283,7 @@ Description: the UNIX units database. This can increase legibility and convenience, and is helpful both as a reminder to the user and as a means for automating the process of checking for consistency of units. - The UNIX units database taken into account is defined in the `nrnunits.lib file `_. - This file includes two versions of the units due to the updates in the values of their base - units. Currently there are legacy and modern units that contain the changes after the updates - introduced on 2019 to the nist constants. The selection between those two versions can be done - using the ``NRN_DYNAMIC_UNITS_USE_LEGACY`` CMake variable or a call to - ``h.nrnunit_use_legacy(bool)`` during runtime. + The UNIX units database (based on the 2019 updated NIST constants) taken into account is defined in the `nrnunits.lib file `_. New units can be defined in terms of default units and previously defined units by placing definitions in the UNITS block. e.g. diff --git a/docs/python/programming/math/constants.rst b/docs/python/programming/math/constants.rst index c73229ece0..f6849671b8 100755 --- a/docs/python/programming/math/constants.rst +++ b/docs/python/programming/math/constants.rst @@ -15,16 +15,13 @@ The following mathematical and physical constants are available through the ``h` h.PHI 1.61803398874989484820 (golden ratio) - h.FARADAY 96484.56 (coulombs/mole) (legacy value) h.FARADAY 96485.3321233100141 (modern value. derived from mole and electron charge) - h.R 8.31441 (molar gas constant, joules/mole/deg-K) (legacy value) h.R 8.3144626181532395 (modern value. derived from boltzmann constant and mole) h.Avogadro_constant 6.02214076e23 (codata2018 value, introduced version 8.0) As of Version 8.0 (circa October, 2020) modern units are the default. -See :func:`nrnunit_use_legacy` .. warning:: Constants are not treated specially by the interpreter and @@ -37,10 +34,4 @@ See :func:`nrnunit_use_legacy` If assignment takes place due to execution of a hoc interpreter statement, the warning occurs only once but cannot be avoided. - - The legacy FARADAY is a bit different than the legacy faraday of the units database. - The legacy faraday in a :file:`.mod` mechanism is 96520. - - - diff --git a/docs/python/simctrl/programmatic.rst b/docs/python/simctrl/programmatic.rst index 02e80356ca..ce082d8498 100755 --- a/docs/python/simctrl/programmatic.rst +++ b/docs/python/simctrl/programmatic.rst @@ -214,22 +214,6 @@ Functions ---- -.. function:: nrnunit_use_legacy - - Syntax: - ``bool = h.nrnunit_use_legacy(bool)`` - - Description: - | Return current units usage as 0 or 1. - | An argument is not required. - | Arg, False uses modern codata2018 units for FARADAY, R, etc. (default as of version 8.0) - | Arg, True uses legacy units (default prior to October, 2020) - - .. seealso:: - :ref:`NRNUNIT_USE_LEGACY` :ref:`CONSTANTS` - ----- - .. data:: secondorder diff --git a/share/lib/nrnunits.lib.in b/share/lib/nrnunits.lib similarity index 95% rename from share/lib/nrnunits.lib.in rename to share/lib/nrnunits.lib index 66481db370..b0839ca173 100755 --- a/share/lib/nrnunits.lib.in +++ b/share/lib/nrnunits.lib @@ -68,10 +68,8 @@ pi 3.14159265358979323846 c 2.99792458+8 m/sec fuzz g 9.80665 m/sec2 au 1.49597871+11 m fuzz -@LegacyY@mole 6.022169+23 fuzz -@LegacyN@mole 6.02214076+23 fuzz -@LegacyY@e 1.6021917-19 coul fuzz -@LegacyN@e 1.602176634-19 coul fuzz +mole 6.02214076+23 fuzz +e 1.602176634-19 coul fuzz energy c2 force g mercury 1.33322+5 kg/m2-sec2 @@ -394,8 +392,7 @@ ev e-volt / faraday 9.652000+04 coul / faraday from host: physics.nist.gov / path: /PhysRefData/fundconst/html/keywords.html -@LegacyY@faraday 9.6485309+4 coul -@LegacyN@faraday e-mole +faraday e-mole fathom 6 ft fermi 1-15 m fifth 4|5 qt @@ -431,8 +428,7 @@ hyl gm force sec2/m hz /sec imaginarycubicfoot 1.4 ft3 jeroboam 4|5 gal -@LegacyY@boltzmann 1.38064852-23 joule/K -@LegacyN@boltzmann 1.380649-23 joule/K +boltzmann 1.380649-23 joule/K k boltzmann karat 1|24 kcal kilocal @@ -501,8 +497,7 @@ quarter 9 in quartersection 1|4 mi2 quintal 100 kg quire 25 -@LegacyY@gasconstant 8.3144598 joule/K -@LegacyN@gasconstant k-mole +gasconstant k-mole R gasconstant rad 100 erg/gm ream 500 @@ -571,10 +566,8 @@ tex .001 gram / m englishell 45 inch scottishell 37.2 inch flemishell 27 inch -@LegacyY@planck 6.626-34 joule-sec -@LegacyN@planck 6.62607015-34 joule-sec -@LegacyY@hbar 1.055-34 joule-sec -@LegacyN@hbar planck/two-pi +planck 6.62607015-34 joule-sec +hbar planck/two-pi electronmass 9.1095-31 kg protonmass 1.6726-27 kg neutronmass 1.6606-27 kg diff --git a/share/lib/python/neuron/expect_hocerr.py b/share/lib/python/neuron/expect_hocerr.py index ead8bdf04f..1b60d89bae 100644 --- a/share/lib/python/neuron/expect_hocerr.py +++ b/share/lib/python/neuron/expect_hocerr.py @@ -41,7 +41,7 @@ def expect_hocerr(callable, args, sec=None): original_stderr = sys.stderr sys.stderr = my_stderr = StringIO() - err = 0 + err = False pyerrmes = False try: if sec: @@ -50,7 +50,7 @@ def expect_hocerr(callable, args, sec=None): callable(*args) printerr("expect_hocerr: no err for %s%s" % (str(callable), str(args))) except Exception as e: - err = 1 + err = True errmes = my_stderr.getvalue() if errmes: errmes = errmes.splitlines()[0] @@ -70,12 +70,12 @@ def expect_err(stmt): """ here = inspect.currentframe() caller = here.f_back - err = 0 + err = False checking(stmt) try: exec(stmt, caller.f_globals, caller.f_locals) printerr("expect_err: no err for-- " + stmt) except Exception as e: - err = 1 + err = True printerr(e) assert err diff --git a/share/lib/python/neuron/rxd/constants.py b/share/lib/python/neuron/rxd/constants.py index a39d6c3299..a318a5dc6d 100644 --- a/share/lib/python/neuron/rxd/constants.py +++ b/share/lib/python/neuron/rxd/constants.py @@ -1,5 +1,3 @@ -# Avogadro's number (approximation before 2019 redefinition) -NA_legacy = 6.02214129e23 NA_modern = 6.02214076e23 @@ -7,10 +5,7 @@ def NA(): try: from neuron import h - # val = NA_legacy if h.nrnunit_use_legacy() else NA_modern val = h.Avogadro_constant - # Note: h.Avogadro_constant is consistent with the above NA legacy and - # modern values. except: val = NA_modern return val @@ -18,6 +13,6 @@ def NA(): def molecules_per_mM_um3(): # converting from mM um^3 to molecules - # = 6.02214129e23 * 1000. / 1.e18 / 1000 + # = 6.02214076e23 * 1000. / 1.e18 / 1000 # = avogadro * (L / m^3) * (m^3 / um^3) * (mM / M) return NA() / 1e18 diff --git a/share/lib/python/neuron/rxd/rxd.py b/share/lib/python/neuron/rxd/rxd.py index 4c382b7ad3..e5f62e8a51 100644 --- a/share/lib/python/neuron/rxd/rxd.py +++ b/share/lib/python/neuron/rxd/rxd.py @@ -254,8 +254,6 @@ def byeworld(): last_diam_change_cnt = None last_structure_change_cnt = None -last_nrn_legacy_units = h.nrnunit_use_legacy() - _all_reactions = [] @@ -570,10 +568,8 @@ def _cxx_compile(formula): def _setup_units(force=False): - global last_nrn_legacy_units if initializer.is_initialized(): - if force or last_nrn_legacy_units != h.nrnunit_use_legacy(): - last_nrn_legacy_units = h.nrnunit_use_legacy() + if force: clear_rates() _setup_memb_currents() _compile_reactions() diff --git a/share/lib/python/neuron/rxdtests/do_test.py b/share/lib/python/neuron/rxdtests/do_test.py index 03654a5b3b..aeadbf7c70 100644 --- a/share/lib/python/neuron/rxdtests/do_test.py +++ b/share/lib/python/neuron/rxdtests/do_test.py @@ -23,7 +23,6 @@ def do_test(test_to_run, results_location, num_record=10): import itertools - h.nrnunit_use_legacy(True) data = {"record_count": 0, "data": []} do_test.data = data record_count = 0 diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index 7937e17088..37c7963078 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -42,7 +42,6 @@ option(CORENRN_ENABLE_CUDA_UNIFIED_MEMORY "Enable CUDA unified memory support" O option(CORENRN_ENABLE_UNIT_TESTS "Enable unit tests execution" ON) option(CORENRN_ENABLE_GPU "Enable GPU support using OpenACC or OpenMP" OFF) option(CORENRN_ENABLE_SHARED "Enable shared library build" ON) -option(CORENRN_ENABLE_LEGACY_UNITS "Enable legacy FARADAY, R, etc" OFF) option(CORENRN_ENABLE_PRCELLSTATE "Enable NRN_PRCELLSTATE debug feature" OFF) set(CORENRN_NMODL_DIR @@ -244,17 +243,6 @@ if(CORENRN_ENABLE_REPORTING) include_directories(${sonatareport_INCLUDE_DIR}) endif() -if(CORENRN_ENABLE_LEGACY_UNITS) - set(CORENRN_USE_LEGACY_UNITS 1) -else() - set(CORENRN_USE_LEGACY_UNITS 0) -endif() -list(APPEND CORENRN_COMPILE_DEFS CORENEURON_USE_LEGACY_UNITS=${CORENRN_USE_LEGACY_UNITS}) -# Propagate Legacy Units flag to backends. -set(NMODL_ENABLE_LEGACY_UNITS - ${CORENRN_ENABLE_LEGACY_UNITS} - CACHE BOOL "" FORCE) - if(CORENRN_ENABLE_PRCELLSTATE) set(CORENRN_NRN_PRCELLSTATE 1) else() @@ -800,7 +788,6 @@ if(NRN_ENABLE_MPI) endif() endif() message(STATUS "OpenMP | ${CORENRN_ENABLE_OPENMP}") -message(STATUS "Use legacy units | ${CORENRN_ENABLE_LEGACY_UNITS}") message(STATUS "NMODL PATH | ${CORENRN_NMODL_BINARY}") message(STATUS "NMODL FLAGS | ${CORENRN_NMODL_FLAGS}") message(STATUS "GPU Support | ${CORENRN_ENABLE_GPU}") diff --git a/src/coreneuron/apps/main1.cpp b/src/coreneuron/apps/main1.cpp index 351b2842b5..6bea87dc5f 100644 --- a/src/coreneuron/apps/main1.cpp +++ b/src/coreneuron/apps/main1.cpp @@ -52,11 +52,6 @@ const char* corenrn_version() { return coreneuron::bbcore_write_version; } -// the CORENEURON_USE_LEGACY_UNITS determined by CORENRN_ENABLE_LEGACY_UNITS -bool corenrn_units_use_legacy() { - return CORENEURON_USE_LEGACY_UNITS; -} - void (*nrn2core_part2_clean_)(); /** diff --git a/src/coreneuron/io/global_vars.cpp b/src/coreneuron/io/global_vars.cpp index 815423ea92..1dc5a5effc 100644 --- a/src/coreneuron/io/global_vars.cpp +++ b/src/coreneuron/io/global_vars.cpp @@ -141,14 +141,6 @@ void set_globals(const char* path, bool cli_global_seed, int cli_global_seed_val secondorder = n; } else if (strcmp(name, "Random123_globalindex") == 0) { nrnran123_set_globalindex((uint32_t) n); - } else if (strcmp(name, "_nrnunit_use_legacy_") == 0) { - if (n != CORENEURON_USE_LEGACY_UNITS) { - hoc_execerror( - "CORENRN_ENABLE_LEGACY_UNITS not" - " consistent with NEURON value of" - " nrnunit_use_legacy()", - nullptr); - } } } } diff --git a/src/coreneuron/utils/units.hpp b/src/coreneuron/utils/units.hpp index de44343fe6..0e73d38dc0 100644 --- a/src/coreneuron/utils/units.hpp +++ b/src/coreneuron/utils/units.hpp @@ -8,14 +8,10 @@ #pragma once namespace coreneuron { namespace units { -#if CORENEURON_USE_LEGACY_UNITS == 1 -constexpr double faraday{96485.309}; -constexpr double gasconstant{8.3134}; -#else /* NMODL translated MOD files get unit constants typically from - * share/lib/nrnunits.lib.in. But there were other source files that hardcode + * share/lib/nrnunits.lib. But there were other source files that hardcode * some of the constants. Here we gather a few modern units into a single place - * (but, unfortunately, also in nrnunits.lib.in). Legacy units cannot be + * (but, unfortunately, also in nrnunits.lib). Legacy units cannot be * gathered here because they can differ slightly from place to place. * * These come from https://physics.nist.gov/cuu/Constants/index.html. @@ -33,6 +29,5 @@ constexpr double faraday{detail::electron_charge * detail::avogadro_number}; // // coulomb/mol constexpr double gasconstant{detail::boltzmann * detail::avogadro_number}; // 8.314462618... // joule/mol-K -#endif } // namespace units } // namespace coreneuron diff --git a/src/modlunit/units.cpp b/src/modlunit/units.cpp index a4cbc1e16a..5f67ca1d2b 100644 --- a/src/modlunit/units.cpp +++ b/src/modlunit/units.cpp @@ -12,32 +12,6 @@ #include -/** - The strategy for dynamic units selection between Legacy and modern units - is to maintain two complete tables respectively. Legacy and modern in the - nrnunits.lib.in file are distinquished by, e.g., - @LegacyY@faraday 9.6485309+4 coul - @LegacyN@faraday 96485.3321233100184 coul - The reason for two complete tables, as opposed to a main table and several - short legacy and modern tables, is that units are often defined in terms - of modified units. eg, "R = (k-mole) (joule/degC)" - - Nmodl, via the parser, uses only unit_pop, unit_mag, Unit_push, - install_units, unit_div, and modl_units. - - The issue of unit magnitude arises only when declaring a unit factor as in - the gasconstant (R) above or with the equivalent "name = (unit) -> (unit)" - syntax. If the magnitude difers between legacy and modern, then instead of - emitting code like "static double FARADAY = 96485.3;\n" we can emit - #define FARADAY _nrnunit_FARADAY_[_nrnunit_use_legacy_] - static double _nrnunit_FARADAY_[2] = {96485.3321233100184, 96485.3}; -**/ - -/* modlunit can do its thing in the old way */ -#if !defined(NRN_DYNAMIC_UNITS) -#define NRN_DYNAMIC_UNITS 0 -#endif - #ifdef MINGW #include "../mswin/extra/d2upath.cpp" #endif @@ -60,19 +34,13 @@ extern void diag(const char*, const char*); #define NTAB 601 -#if NRN_DYNAMIC_UNITS -#define SUFFIX ".in" -#else -#define SUFFIX "" -#endif - /* if MODLUNIT environment variable not set then look in the following places*/ #if defined(NEURON_DATA_DIR) -static const char* dfile = NEURON_DATA_DIR "/lib/nrnunits.lib" SUFFIX; +static char const* const dfile = NEURON_DATA_DIR "/lib/nrnunits.lib"; #else -static const char* dfile = "/usr/lib/units"; +static char const* const dfile = "/usr/lib/units"; #endif -static const char* dfilealt = "../../share/lib/nrnunits.lib" SUFFIX; +static char const* const dfilealt = "../../share/lib/nrnunits.lib"; static char* unames[NDIM]; double getflt(); void fperr(int); @@ -100,13 +68,6 @@ static struct table { static char* names; -#if NRN_DYNAMIC_UNITS -static struct dynam { - struct table* table; /* size NTAB */ - char* names; /* size NTAB*10 */ -} dynam[2]; -#endif - static struct prefix { double factor; const char* pname; @@ -330,23 +291,8 @@ static void install_units_help(char* s1, char* s2) /* define s1 as s2 */ unit_pop(); } -static void switch_units(int legacy) { -#if NRN_DYNAMIC_UNITS - table = dynam[legacy].table; - names = dynam[legacy].names; -#endif -} - void install_units(char* s1, char* s2) { -#if NRN_DYNAMIC_UNITS - int i; - for (i = 0; i < 2; ++i) { - switch_units(i); - install_units_help(s1, s2); - } -#else install_units_help(s1, s2); -#endif } void check_num() { @@ -567,20 +513,10 @@ static void units_alloc() { static int units_alloc_called = 0; if (!units_alloc_called) { units_alloc_called = 1; -#if NRN_DYNAMIC_UNITS - for (i = 0; i < 2; ++i) { - dynam[i].table = (struct table*) calloc(NTAB, sizeof(struct table)); - assert(dynam[i].table); - dynam[i].names = (char*) calloc(NTAB * 10, sizeof(char)); - assert(dynam[i].names); - switch_units(i); - } -#else table = (struct table*) calloc(NTAB, sizeof(struct table)); assert(table); names = (char*) calloc(NTAB * 10, sizeof(char)); assert(names); -#endif } } @@ -592,14 +528,7 @@ void modl_units() { unitonflag = 1; if (first) { units_alloc(); -#if NRN_DYNAMIC_UNITS - for (i = 0; i < 2; ++i) { - switch_units(i); - unit_init(); - } -#else unit_init(); -#endif first = 0; } } @@ -615,7 +544,7 @@ void unit_init() { /* note that on mingw, even if MODLUNIT set to /cygdrive/c/... * it ends up here as c:/... and that is good*/ /* printf("MODLUNIT=|%s|\n", s); */ - Sprintf(buf, "%s%s", s, SUFFIX); + Sprintf(buf, "%s", s); if ((inpfile = fopen(buf, "r")) == (FILE*) 0) { diag("Bad MODLUNIT environment variable. Cant open:", buf); } @@ -626,9 +555,9 @@ void unit_init() { if (s) { if (strncmp(s, "/cygdrive/", 10) == 0) { /* /cygdrive/x/... to c:/... */ - Sprintf(buf, "%c:%s/lib/nrnunits.lib" SUFFIX, s[10], s + 11); + Sprintf(buf, "%c:%s/lib/nrnunits.lib", s[10], s + 11); } else { - Sprintf(buf, "%s/lib/nrnunits.lib" SUFFIX, s); + Sprintf(buf, "%s/lib/nrnunits.lib", s); } inpfile = fopen(buf, "r"); free(s); @@ -639,7 +568,7 @@ void unit_init() { if ((inpfile = fopen(dfilealt, "r")) == (FILE*) 0) { s = neuronhome(); if (s) { - Sprintf(buf, "%s/lib/nrnunits.lib" SUFFIX, s); + Sprintf(buf, "%s/lib/nrnunits.lib", s); inpfile = fopen(buf, "r"); } } @@ -656,65 +585,6 @@ void unit_init() { unit_stk_clean(); } -#if 0 -void main(argc, argv) -char *argv[]; -{ - register i; - register char *file; - struct unit u1, u2; - double f; - - if(argc>1 && *argv[1]=='-') { - argc--; - argv++; - dumpflg++; - } - file = dfile; - if(argc > 1) - file = argv[1]; - if ((inpfile = fopen(file, "r")) == NULL) { - printf("no table\n"); - exit(1); - } - signal(8, fperr); - units_cpp_init(); - -loop: - fperrc = 0; - printf("you have: "); - if(convr(&u1)) - goto loop; - if(fperrc) - goto fp; -loop1: - printf("you want: "); - if(convr(&u2)) - goto loop1; - for(i=0; i 1) *ucp++ = (u + '0'); - return (2); + return 2; } if (u < 0) - return (1); - return (0); + return 1; + return 0; } int convr(unit* up) { @@ -782,7 +652,7 @@ int convr(unit* up) { if (c == '/') den++; if (c == '\n') - return (err); + return err; goto loop; } *cp++ = c; @@ -815,7 +685,7 @@ int lookup(char* name, unit* up, int den, int c) { c--; goto l1; } - return (0); + return 0; } { const char* cp1{}; @@ -847,14 +717,14 @@ int lookup(char* name, unit* up, int den, int c) { name); diag("Cannot recognize the units: ", name); /* printf("cannot recognize %s\n", name);*/ - return (1); + return 1; } static int equal(const char* c1, const char* c2) { while (*c1++ == *c2) if (*c2++ == 0) - return (1); - return (0); + return 1; + return 0; } void units_cpp_init() { @@ -882,9 +752,6 @@ void units_cpp_init() { l0: c = get(); if (c == 0) { -#if 0 - printf("%d units; %ld bytes\n\n", i, cp-names); -#endif if (dumpflg) for (tp = table; tp < table + NTAB; tp++) { if (tp->name == 0) @@ -903,36 +770,6 @@ void units_cpp_init() { goto l0; } -#if NRN_DYNAMIC_UNITS - if (c == '@') { - /** - Dynamic unit line beginning with @LegacyY@ or @LegacyN@. - If the Y or N does not match the modern or legacy table, skip the - entire line. For a match, just leave file at char after the final '@'. - **/ - int i; - int legacy; - char legstr[7]; - char y_or_n; - for (i = 0; i < 6; ++i) { - legstr[i] = get(); - } - legstr[6] = '\0'; - assert(strcmp(legstr, "Legacy") == 0); - y_or_n = get(); - assert(y_or_n == 'Y' || y_or_n == 'N'); - legacy = (y_or_n == 'Y') ? 1 : 0; - nrn_assert(get() == '@'); - if (dynam[legacy].table != table) { /* skip the line */ - while (c != '\n' && c != 0) { - c = get(); - } - goto l0; - } - c = get(); - } -#endif - if (c == '\n') goto l0; @@ -984,18 +821,12 @@ void units_cpp_init() { goto l0; } -#if NRN_DYNAMIC_UNITS -/* Translate string to double using a2f for modern units - to allow consistency with BlueBrain/nmodl -*/ -double modern_getflt() { +double getflt() { int c; char str[100]; char* cp; double d_modern; - assert(table == dynam[0].table); - cp = str; do c = get(); @@ -1024,73 +855,11 @@ double modern_getflt() { *cp = '\0'; d_modern = atof(str); if (c == '|') { - d_modern /= modern_getflt(); + d_modern /= getflt(); return d_modern; } peekc = c; - return (d_modern); -} -#endif /* NRN_DYNAMIC_UNITS */ - -double getflt() { - int c, i, dp; - double d, e; - int f; - -#if NRN_DYNAMIC_UNITS - if (table == dynam[0].table) { - return modern_getflt(); - } -#endif /* NRN_DYNAMIC_UNITS */ - d = 0.; - dp = 0; - do - c = get(); - while (c == ' ' || c == '\t'); - -l1: - if (c >= '0' && c <= '9') { - d = d * 10. + c - '0'; - if (dp) - dp++; - c = get(); - goto l1; - } - if (c == '.') { - dp++; - c = get(); - goto l1; - } - if (dp) - dp--; - if (c == '+' || c == '-') { - f = 0; - if (c == '-') - f++; - i = 0; - c = get(); - while (c >= '0' && c <= '9') { - i = i * 10 + c - '0'; - c = get(); - } - if (f) - i = -i; - dp -= i; - } - e = 1.; - i = dp; - if (i < 0) - i = -i; - while (i--) - e *= 10.; - if (dp < 0) - d *= e; - else - d /= e; - if (c == '|') - return (d / getflt()); - peekc = c; - return (d); + return d_modern; } int get() { @@ -1099,7 +868,7 @@ int get() { /*SUPPRESS 560*/ if ((c = peekc) != 0) { peekc = 0; - return (c); + return c; } c = Getc(inpfile); if (c == '\r') { @@ -1110,9 +879,9 @@ int get() { printf("\n"); exit(0); } - return (0); + return 0; } - return (c); + return c; } struct table* hash_table(const char* name) { @@ -1130,9 +899,9 @@ struct table* hash_table(const char* name) { tp = &table[h]; l0: if (tp->name == 0) - return (tp); + return tp; if (equal(name, tp->name)) - return (tp); + return tp; tp++; if (tp >= table + NTAB) tp = table; @@ -1144,43 +913,10 @@ void fperr(int sig) { fperrc++; } -static double dynam_unit_mag(int legacy, char* u1, char* u2) { - double result; - switch_units(legacy); - Unit_push(u1); - Unit_push(u2); - unit_div(); - result = unit_mag(); - unit_pop(); - return result; -} - -void nrnunit_dynamic_str(char (&buf)[NRN_BUFSIZE], const char* name, char* u1, char* u2) { -#if NRN_DYNAMIC_UNITS - - double legacy = dynam_unit_mag(1, u1, u2); - double modern = dynam_unit_mag(0, u1, u2); - Sprintf(buf, - "\n" - "#define %s _nrnunit_%s[_nrnunit_use_legacy_]\n" - "static double _nrnunit_%s[2] = {%a, %g};\n", - name, - name, - name, - modern, - legacy); - -#else - +void nrnunit_str(char (&buf)[NRN_BUFSIZE], const char* name, const char* u1, const char* u2) { Unit_push(u1); Unit_push(u2); unit_div(); -#if (defined(LegacyFR) && LegacyFR == 1) - Sprintf(buf, "static double %s = %g;\n", name, unit_mag()); -#else Sprintf(buf, "static double %s = %a;\n", name, unit_mag()); -#endif unit_pop(); - -#endif } diff --git a/src/nmodl/nmodlfunc.h b/src/nmodl/nmodlfunc.h index 2f979161f7..917fa7a56e 100644 --- a/src/nmodl/nmodlfunc.h +++ b/src/nmodl/nmodlfunc.h @@ -138,4 +138,4 @@ void netrec_asgn(Item* varname, Item* equal, Item* expr, Item* lastok); void netrec_discon(); char* items_as_string(Item* begin, Item* last); /* does not include last */ int slist_search(int listnum, Symbol* s); -void nrnunit_dynamic_str(char (&buf)[NRN_BUFSIZE], const char* name, char* unit1, char* unit2); +void nrnunit_str(char (&buf)[NRN_BUFSIZE], const char* name, const char* unit1, const char* unit2); diff --git a/src/nmodl/parse1.ypp b/src/nmodl/parse1.ypp index 342b354049..a8707c44b0 100755 --- a/src/nmodl/parse1.ypp +++ b/src/nmodl/parse1.ypp @@ -924,13 +924,13 @@ factordef: NAME '=' real unit | NAME '=' unit unit { SYM($1)->subtype |= nmodlCONST; - nrnunit_dynamic_str(buf, SYM($1)->name, $3, $4); + nrnunit_str(buf, SYM($1)->name, $3, $4); Lappendstr(firstlist, buf); } | NAME '=' unit '-' GT unit { SYM($1)->subtype |= nmodlCONST; - nrnunit_dynamic_str(buf, SYM($1)->name, $3, $6); + nrnunit_str(buf, SYM($1)->name, $3, $6); Lappendstr(firstlist, buf); } | error {myerr("Unit factor syntax: examples:\n\ diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index 0e2064ac4d..8fa79ca530 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -91,7 +91,7 @@ add_dependencies(generated_source_files nocmodl_generated_files) add_executable(nocmodl ${NRN_NMODL_SRC_FILES} "${NRN_NMODL_GEN}/lex.cpp" "${NRN_NMODL_GEN}/parse1.cpp" "${NRN_NMODL_GEN}/diffeq.cpp") cpp_cc_configure_sanitizers(TARGET nocmodl) -target_compile_definitions(nocmodl PRIVATE COMPILE_DEFINITIONS NMODL=1 CVODE=1 NRN_DYNAMIC_UNITS=1) +target_compile_definitions(nocmodl PRIVATE COMPILE_DEFINITIONS NMODL=1 CVODE=1) # Otherwise the generated code in the binary directory does not find headers in the modlunit source # directory and the source files in the source directory do not find generated headers in the binary # directory. diff --git a/src/nrniv/kschan.h b/src/nrniv/kschan.h index 02f4a868d8..ff05871618 100644 --- a/src/nrniv/kschan.h +++ b/src/nrniv/kschan.h @@ -5,7 +5,7 @@ #include #include "nrnoc2iv.h" #include "ivocvect.h" -#include "nrnunits_modern.h" +#include "nrnunits.h" #include "spmatrix.h" @@ -95,10 +95,7 @@ class KSChanSigmoid: public KSChanFunction { }; -// e/(kT) e/k=11.604589 from hoc's FARADAY and R values (legacy units) -#define _e_over_k _e_over_k_[_nrnunit_use_legacy_] -static double _e_over_k_[2] = {_e_over_k_codata2018, 11.604589}; /* K/mV */ -#define ebykt (_e_over_k / (273.15 + celsius)) +#define ebykt (_e_over_k_codata2018 / (273.15 + celsius)) // from MODELING NEURONAL BIOPHYSICS Lyle J Graham // A Chapter in the Handbook of Brain Theory and Neural Networks, Volume 2 diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 05d0f90e56..49a1bf6806 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -74,8 +74,6 @@ int get_global_int_item(const char* name) { return secondorder; } else if (strcmp(name, "Random123_global_index") == 0) { return nrnran123_get_globalindex(); - } else if (strcmp(name, "_nrnunit_use_legacy_") == 0) { - return _nrnunit_use_legacy_; } return 0; } diff --git a/src/nrniv/nrncore_write/io/nrncore_io.cpp b/src/nrniv/nrncore_write/io/nrncore_io.cpp index ef41bc3f48..094e727093 100644 --- a/src/nrniv/nrncore_write/io/nrncore_io.cpp +++ b/src/nrniv/nrncore_write/io/nrncore_io.cpp @@ -108,7 +108,6 @@ void write_globals(const char* fname) { fprintf(f, "0 0\n"); fprintf(f, "secondorder %d\n", secondorder); fprintf(f, "Random123_globalindex %d\n", nrnran123_get_globalindex()); - fprintf(f, "_nrnunit_use_legacy_ %d\n", _nrnunit_use_legacy_); fclose(f); } diff --git a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp index 041d916904..5a24cad859 100644 --- a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp +++ b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp @@ -267,18 +267,6 @@ void check_coreneuron_compatibility(void* handle) { s_path << bbcore_write_version << " vs " << cn_bbcore_read_version; hoc_execerror("Incompatible NEURON and CoreNEURON versions :", s_path.str().c_str()); } - - // Make sure legacy vs modern units are consistent. - // Would be nice to check in coreneuron set_globals but that would abort - // if inconsistent. - void* cn_nrnunit_use_legacy_sym = dlsym(handle, "corenrn_units_use_legacy"); - if (!cn_nrnunit_use_legacy_sym) { - hoc_execerror("Could not get symbol corenrn_units_use_legacy from CoreNEURON", NULL); - } - bool cn_nrnunit_use_legacy = (*(bool (*)()) cn_nrnunit_use_legacy_sym)(); - if (cn_nrnunit_use_legacy != (_nrnunit_use_legacy_ == 1)) { - hoc_execerror("nrnunit_use_legacy() inconsistent with CORENRN_ENABLE_LEGACY_UNITS", NULL); - } } #endif //! HAVE_DLFCN_H diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index 58de6f4c19..602eac5e58 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -9,7 +9,7 @@ #include "parse.hpp" #include "membdef.h" #include "nrniv_mf.h" -#include "nrnunits_modern.h" +#include "nrnunits.h" #include #include @@ -262,12 +262,7 @@ at least one model using this ion\n", } } -#define FARADAY _faraday_[_nrnunit_use_legacy_] -static double _faraday_[2] = {_faraday_codata2018, 96485.309}; -#define gasconstant _gasconstant_[_nrnunit_use_legacy_] -static double _gasconstant_[2] = {_gasconstant_codata2018, 8.3134}; - -#define ktf (1000. * gasconstant * (celsius + 273.15) / FARADAY) +#define ktf (1000. * _gasconstant_codata2018 * (celsius + 273.15) / _faraday_codata2018) double nrn_nernst(double ci, double co, double z) { /*printf("nrn_nernst %g %g %g\n", ci, co, z);*/ if (z == 0) { @@ -343,7 +338,7 @@ double nrn_ghk(double v, double ci, double co, double z) { temp = z * v / ktf; eco = co * efun(temp); eci = ci * efun(-temp); - return (.001) * z * FARADAY * (eci - eco); + return (.001) * z * _faraday_codata2018 * (eci - eco); } void ghk(void) { diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index c4ca6229a1..5ed479a2a6 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -1113,9 +1113,15 @@ double nrn_call_mech_func(Symbol* s, int narg, Prop* p, int type) { } void nrnunit_use_legacy() { + hoc_warning("nrnunit_use_legacy() is deprecated as only modern units are supported.", + "If you want to still use legacy unit you can use a version of nrn < 9."); if (ifarg(1)) { int arg = (int) chkarg(1, 0, 1); - _nrnunit_use_legacy_ = arg; + if (arg == 1) { + hoc_execerror( + "'nrnunit_use_legacy(1)' have been called but legacy units are no more supported.", + nullptr); + } } - hoc_retpushx((double) _nrnunit_use_legacy_); + hoc_retpushx(0.); // This value means modern unit } diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 6414df11a6..4f7971ee90 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -1496,14 +1496,6 @@ static int hocobj_setattro(PyObject* subself, PyObject* pyname, PyObject* value) return -1; } err = PyArg_Parse(value, "d", hoc_pxpop()) == 0; - if (!err && sym->subtype == DYNAMICUNITS) { - char mes[100]; - Sprintf(mes, - "Assignment to %s value of physical constant %s", - _nrnunit_use_legacy_ ? "legacy" : "modern", - sym->name); - err = PyErr_WarnEx(PyExc_Warning, mes, 1); - } } } break; diff --git a/src/nrnpython/rxd.cpp b/src/nrnpython/rxd.cpp index a8a1b25ec4..56fcf0b355 100644 --- a/src/nrnpython/rxd.cpp +++ b/src/nrnpython/rxd.cpp @@ -17,9 +17,7 @@ static void ode_solve(double, double*, double*); extern PyTypeObject* hocobject_type; extern int structure_change_cnt; extern int states_cvode_offset; -extern int _nrnunit_use_legacy_; int prev_structure_change_cnt = 0; -int prev_nrnunit_use_legacy = _nrnunit_use_legacy_; unsigned char initialized = FALSE; /* @@ -772,10 +770,6 @@ extern "C" int rxd_nonvint_block(int method, int size, double* p1, double* p2, i /*Needed for node.include_flux*/ _setup_matrices(); } - if (prev_nrnunit_use_legacy != _nrnunit_use_legacy_) { - _setup_units(); - prev_nrnunit_use_legacy = _nrnunit_use_legacy_; - } } switch (method) { case 0: diff --git a/src/oc/code.cpp b/src/oc/code.cpp index d00a24bf7d..f3d8a58db4 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -1027,19 +1027,6 @@ void forcode(void) { pc = relative(savepc + 1); /* next statement */ } -static void warn_assign_dynam_unit(const char* name) { - static int first = 1; - if (first) { - char mes[100]; - first = 0; - Sprintf(mes, - "Assignment to %s physical constant %s", - _nrnunit_use_legacy_ ? "legacy" : "modern", - name); - hoc_warning(mes, NULL); - } -} - void hoc_shortfor(void) { Inst* savepc = pc; double begin, end, *pval = 0; @@ -1059,9 +1046,6 @@ void hoc_shortfor(void) { execerror("integer iteration variable", sym->name); } else if (sym->subtype == USERDOUBLE) { pval = sym->u.pval; - } else if (sym->subtype == DYNAMICUNITS) { - pval = sym->u.pval + _nrnunit_use_legacy_; - warn_assign_dynam_unit(sym->name); } else { pval = OPVAL(sym); } @@ -1222,9 +1206,6 @@ static void for_segment2(Symbol* sym, int mode) { execerror("integer iteration variable", sym->name); } else if (sym->subtype == USERDOUBLE) { pval = sym->u.pval; - } else if (sym->subtype == DYNAMICUNITS) { - pval = sym->u.pval + _nrnunit_use_legacy_; - warn_assign_dynam_unit(sym->name); } else { pval = OPVAL(sym); } @@ -1875,9 +1856,6 @@ void eval(void) /* evaluate variable on stack */ case USERINT: d = (double) (*(sym->u.pvalint)); break; - case DYNAMICUNITS: - d = sym->u.pval[_nrnunit_use_legacy_]; - break; case USERPROPERTY: d = cable_prop_eval(sym); break; @@ -1959,9 +1937,6 @@ void hoc_evalpointer() { case USERFLOAT: execerror("can use pointer only to doubles", sym->name); break; - case DYNAMICUNITS: - d = sym->u.pval + _nrnunit_use_legacy_; - break; case USERPROPERTY: d = cable_prop_eval_pointer(sym); break; @@ -2238,13 +2213,6 @@ void hoc_assign() { } *(sym->u.pvalfloat) = (float) (d2); break; - case DYNAMICUNITS: - if (op) { - d2 = hoc_opasgn(op, sym->u.pval[_nrnunit_use_legacy_], d2); - } - sym->u.pval[_nrnunit_use_legacy_] = (float) (d2); - warn_assign_dynam_unit(sym->name); - break; default: if (op) { d2 = hoc_opasgn(op, *(OPVAL(sym)), d2); diff --git a/src/oc/hoc_init.cpp b/src/oc/hoc_init.cpp index a3d6438365..6e022f7047 100644 --- a/src/oc/hoc_init.cpp +++ b/src/oc/hoc_init.cpp @@ -5,7 +5,7 @@ #include "parse.hpp" #include #include "equation.h" -#include "nrnunits_modern.h" +#include "nrnunits.h" #include "nrn_ansi.h" #include "ocfunc.h" @@ -78,19 +78,11 @@ static struct { /* Constants */ {"GAMMA", 0.57721566490153286060}, /* Euler */ {"DEG", 57.29577951308232087680}, /* deg/radian */ {"PHI", 1.61803398874989484820}, /* golden ratio */ - {nullptr, 0}}; - -/* Nov, 2017, from https://physics.nist.gov/cuu/Constants/index.html */ -/* also see FARADAY and gasconstant in ../nrnoc/eion.c */ -static struct { /* Modern, Legacy units constants */ - const char* name; - double cval[2]; -} uconsts[] = {{"FARADAY", {_faraday_codata2018, 96485.309}}, /*coulombs/mole*/ - {"R", {_gasconstant_codata2018, 8.31441}}, /*molar gas constant, joules/mole/deg-K*/ - {"Avogadro_constant", - {_avogadro_number_codata2018, 6.02214129e23}}, /* note that the legacy value in + {"FARADAY", _faraday_codata2018}, /*coulombs/mole*/ + {"R", _gasconstant_codata2018}, /*molar gas constant, joules/mole/deg-K*/ + {"Avogadro_constant", _avogadro_number_codata2018}, /* note that the legacy value in nrnunits.lib.in is 6.022169+23 */ - {0, {0., 0.}}}; + {nullptr, 0}}; static struct { /* Built-ins */ const char* name; @@ -241,25 +233,24 @@ const char* nrn_mech_dll; /* but actually only for NEURON mswin and linux * int nrn_noauto_dlopen_nrnmech; /* 0 except when binary special. */ int use_mcell_ran4_; int nrn_xopen_broadcast_; -int _nrnunit_use_legacy_; /* allow dynamic switching between legacy and modern units */ void hoc_init(void) /* install constants and built-ins table */ { int i; Symbol* s; -#if defined(DYNAMIC_UNITS_USE_LEGACY_DEFAULT) - _nrnunit_use_legacy_ = 1; /* legacy as default */ -#else - _nrnunit_use_legacy_ = 0; /* new units as default */ -#endif - { /* but check the environment variable if it exists */ + { const char* envvar = getenv("NRNUNIT_USE_LEGACY"); if (envvar) { + hoc_warning( + "NRNUNIT_USE_LEGACY is deprecated as only modern units are supported with NEURON " + "version >= 9", + "If you want to still use legacy unit you can use a NEURON version < 9"); if (strcmp(envvar, "1") == 0) { - _nrnunit_use_legacy_ = 1; - } else if (strcmp(envvar, "0") == 0) { - _nrnunit_use_legacy_ = 0; + hoc_execerror( + "'NRNUNIT_USE_LEGACY=1' is set but legacy units support is removed with NEURON " + "version >= 9", + nullptr); } } } @@ -276,12 +267,6 @@ void hoc_init(void) /* install constants and built-ins table */ s->u.pval = &consts[i].cval; s->subtype = USERDOUBLE; } - for (i = 0; uconsts[i].name; i++) { - s = install(uconsts[i].name, UNDEF, uconsts[i].cval[0], &symlist); - s->type = VAR; - s->u.pval = &uconsts[i].cval[0]; - s->subtype = DYNAMICUNITS; - } for (i = 0; builtins[i].name; i++) { s = install(builtins[i].name, BLTIN, 0.0, &symlist); s->u.ptr = builtins[i].func; diff --git a/src/oc/nrnunits.h b/src/oc/nrnunits.h new file mode 100644 index 0000000000..e8f777a686 --- /dev/null +++ b/src/oc/nrnunits.h @@ -0,0 +1,30 @@ +#ifndef nrnunits_modern_h +#define nrnunits_modern_h + +/** + NMODL translated MOD files get unit constants typically from + share/lib/nrnunits.lib. But there were other source files that + hardcode some of the constants. Here we gather a few modern units into + a single place (but, unfortunately, also in nrnunits.lib). + + These come from https://physics.nist.gov/cuu/Constants/index.html. + Termed the "2018 CODATA recommended values", they became available + on 20 May 2019 and replace the 2014 CODATA set. + + See oc/hoc_init.c, nrnoc/eion.c, nrniv/kschan.h +**/ + + +constexpr double _electron_charge_codata2018 = 1.602176634e-19; /* coulomb exact*/ +constexpr double _avogadro_number_codata2018 = 6.02214076e+23; /* exact */ +constexpr double _boltzmann_codata2018 = 1.380649e-23; /* joule/K exact */ +constexpr double _faraday_codata2018 = _electron_charge_codata2018 * + _avogadro_number_codata2018; /* 96485.33212... coulomb/mol */ +constexpr double _gasconstant_codata2018 = + _boltzmann_codata2018 * _avogadro_number_codata2018; /* 8.314462618... joule/mol-K */ + +/* 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/nrnunits_modern.h b/src/oc/nrnunits_modern.h deleted file mode 100644 index 50c26b3ae9..0000000000 --- a/src/oc/nrnunits_modern.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef nrnunits_modern_h -#define nrnunits_modern_h - -/** - NMODL translated MOD files get unit constants typically from - share/lib/nrnunits.lib.in. But there were other source files that - hardcode some of the constants. Here we gather a few modern units into - a single place (but, unfortunately, also in nrnunits.lib.in). Legacy units - cannot be gathered here because they can differ slightly from place to place. - - These come from https://physics.nist.gov/cuu/Constants/index.html. - Termed the "2018 CODATA recommended values", they became available - on 20 May 2019 and replace the 2014 CODATA set. - - See oc/hoc_init.c, nrnoc/eion.c, nrniv/kschan.h -**/ - - -#define _electron_charge_codata2018 1.602176634e-19 /* coulomb exact*/ -#define _avogadro_number_codata2018 6.02214076e+23 /* exact */ -#define _boltzmann_codata2018 1.380649e-23 /* joule/K exact */ -#define _faraday_codata2018 \ - (_electron_charge_codata2018 * _avogadro_number_codata2018) /* 96485.33212... coulomb/mol */ -#define _gasconstant_codata2018 \ - (_boltzmann_codata2018 * _avogadro_number_codata2018) /* 8.314462618... joule/mol-K */ - -/* e/k in K/millivolt */ -#define _e_over_k_codata2018 \ - (.001 * _electron_charge_codata2018 / _boltzmann_codata2018) /* 11.604518... K/mV */ - -#endif /* nrnunits_modern_h */ diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index 130842b17d..399a86e408 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -431,7 +431,6 @@ int nrn_is_cable(); void* nrn_opaque_obj2pyobj(Object*); // PyObject reference not incremented Symbol* hoc_get_symbol(const char* var); -extern int _nrnunit_use_legacy_; /* 1:legacy, 0:modern (default) */ void bbs_done(void); int hoc_main1(int, const char**, const char**); char* cxx_char_alloc(std::size_t size); diff --git a/test/coreneuron/test_units.py b/test/coreneuron/test_units.py index 80bae28ad3..742aeb2f9d 100644 --- a/test/coreneuron/test_units.py +++ b/test/coreneuron/test_units.py @@ -1,4 +1,5 @@ from neuron.tests.utils.strtobool import strtobool +from neuron.expect_hocerr import expect_err import os from neuron import h @@ -7,6 +8,12 @@ def test_units(): + # should just emit warning + h.nrnunit_use_legacy(0) + + # should generate an error + expect_err("h.nrnunit_use_legacy(1)") + s = h.Section() pp = h.UnitsTest(s(0.5)) h.ion_style("na_ion", 1, 2, 1, 1, 0, sec=s) diff --git a/test/external/CMakeLists.txt b/test/external/CMakeLists.txt index 2931efccdb..6026122a62 100644 --- a/test/external/CMakeLists.txt +++ b/test/external/CMakeLists.txt @@ -19,7 +19,7 @@ FetchContent_Declare( FetchContent_Declare( nrntest GIT_REPOSITORY https://github.com/neuronsimulator/nrntest - GIT_TAG fe7029e38f518787fd61fb61b0d861f680cbcf39 + GIT_TAG 8f7cf8f9301bfef386601309747e2440a3c11830 SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/nrntest) FetchContent_Declare( diff --git a/test/pytest_coreneuron/test_units.py b/test/pytest_coreneuron/test_units.py deleted file mode 100644 index 1f191b4357..0000000000 --- a/test/pytest_coreneuron/test_units.py +++ /dev/null @@ -1,102 +0,0 @@ -from neuron import h - - -def switch_units(legacy): - try: - h.nrnunit_use_legacy(legacy) - except: - pass - - -def test_mod_legacy(): - s = h.Section() - ut = h.UnitsTest(s(0.5)) - h.ion_style("na_ion", 1, 2, 1, 1, 0, sec=s) - switch_units(1) - h.finitialize() - names = ["mole", "e", "faraday", "planck", "hbar", "gasconst"] - legacy_hex_values = [ - "0x1.fe18fef60659ap+78", - "0x1.7a4e7164efbbcp-63", - "0x1.78e54cccccccdp+16", - "0x1.b85f8c5445f02p-111", - "0x1.18779454e3d48p-113", - "0x1.0a10624dd2f1bp+3", - ] - for i, n in enumerate(names): - val = eval("ut." + n) - print("%s = %s (%s)" % (n, str(val.hex()), str(val))) - legacy_value = float.fromhex(legacy_hex_values[i]) - assert val == legacy_value - assert ut.avogadro == float.fromhex(legacy_hex_values[0]) - ghk_std = h.ghk(-50, 0.001, 10, 2) - erev_std = h.nernst(s(0.5).nai, s(0.5).nao, 1) - assert ut.ghk == ghk_std - assert ut.erev == erev_std - switch_units(0) - h.finitialize() - ghk_std = h.ghk(-50, 0.001, 10, 2) - erev_std = h.nernst(s(0.5).nai, s(0.5).nao, 1) - assert ut.mole != float.fromhex(legacy_hex_values[0]) - assert ut.e * ut.avogadro == ut.faraday - assert abs(ut.faraday - h.FARADAY) < 1e-10 - assert ut.gasconst == h.R - assert ut.gasconst_exact == 8.313424 - assert ut.k * ut.avogadro == ut.gasconst - assert abs(ut.planck - ut.hbar * 2.0 * h.PI) < 1e-49 - assert ut.avogadro == h.Avogadro_constant - assert ut.ghk == h.ghk(-50, 0.001, 10, 2) - assert ut.erev == h.nernst(s(0.5).nai, s(0.5).nao, 1) - - -def test_hoc_legacy(): - switch_units(1) # legacy - print("R = %s" % str(h.R)) - print("FARADAY = %s" % str(h.FARADAY)) - celsius = 6.3 - ghk = h.ghk(30, 0.01, 10, 1) # nernst requires a Section to get voltage - print("ghk = %s" % str(ghk)) - - assert h.R == 8.31441 - assert h.FARADAY == 96485.309 - assert ghk == -483.7914803097116 - - switch_units(0) # Modern - print("R = %s" % str(h.R)) - print("FARADAY = %s" % str(h.FARADAY)) - ghk = h.ghk(30, 0.01, 10, 1) - print("ghk = %s" % str(ghk)) - assert h.R == 8.31446261815324 - assert ghk == -483.8380971405879 - - -def test_env_legacy(): - import os, subprocess, sys - - for i in [0, 1]: - exe = os.environ.get("NRN_PYTHON_EXECUTABLE", sys.executable) - env = os.environ.copy() - env["NRNUNIT_USE_LEGACY"] = str(i) - try: - env[os.environ["NRN_SANITIZER_PRELOAD_VAR"]] = os.environ[ - "NRN_SANITIZER_PRELOAD_VAL" - ] - except: - pass - a = subprocess.check_output( - [ - exe, - "-c", - "from neuron import h; print(h.nrnunit_use_legacy())", - ], - env=env, - shell=False, - ) - a = int(float(a.decode().split()[0])) - assert a == i - - -if __name__ == "__main__": - test_mod_legacy() - test_hoc_legacy() - test_env_legacy() diff --git a/test/rxd/3d/test_multigridding_allowed.py b/test/rxd/3d/test_multigridding_allowed.py index e6f868e032..45a0e87972 100644 --- a/test/rxd/3d/test_multigridding_allowed.py +++ b/test/rxd/3d/test_multigridding_allowed.py @@ -71,21 +71,21 @@ def should_work2(h, rxd): h.fadvance() -def test_no_overlap(neuron_instance): - h, rxd, data, save_path = neuron_instance +def test_no_overlap(neuron_nosave_instance): + h, rxd, save_path = neuron_nosave_instance should_work(h, rxd) -def test_neighbors_with_different_dx_fails(neuron_instance): - h, rxd, data, save_path = neuron_instance +def test_neighbors_with_different_dx_fails(neuron_nosave_instance): + h, rxd, save_path = neuron_nosave_instance expect_hocerr(should_not_work, (h, rxd)) -def test_overlapping_dx_fails(neuron_instance): - h, rxd, data, save_path = neuron_instance +def test_overlapping_dx_fails(neuron_nosave_instance): + h, rxd, save_path = neuron_nosave_instance expect_hocerr(should_not_work2, (h, rxd)) -def test_overlap_same_dx(neuron_instance): - h, rxd, data, save_path = neuron_instance +def test_overlap_same_dx(neuron_nosave_instance): + h, rxd, save_path = neuron_nosave_instance should_work2(h, rxd) diff --git a/test/rxd/3d/test_soma_outlines.py b/test/rxd/3d/test_soma_outlines.py index a35082022f..89607849d0 100644 --- a/test/rxd/3d/test_soma_outlines.py +++ b/test/rxd/3d/test_soma_outlines.py @@ -32,7 +32,7 @@ def __init__(self, shift=(0, 0, 0)): for i in range(sec.n3d()) ] sec.pt3dclear() - for (x, y, z, diam) in pts: + for x, y, z, diam in pts: sec.pt3dadd(x + sx, y + sy, z + sz, diam) yield (h, rxd, data, save_path, Cell) diff --git a/test/rxd/conftest.py b/test/rxd/conftest.py index 40768662a9..1fbe8ee0cc 100644 --- a/test/rxd/conftest.py +++ b/test/rxd/conftest.py @@ -38,8 +38,6 @@ def neuron_nosave_instance(neuron_import): h.load_file("stdrun.hoc") h.load_file("import3d.hoc") - h.nrnunit_use_legacy(True) - # pytest fixtures at the function scope that require neuron_instance will go # out of scope after neuron_instance. So species, sections, etc. will go # out of scope after neuron_instance is torn down. @@ -78,7 +76,6 @@ def neuron_nosave_instance(neuron_import): rxd.section1d._purge_cptrs() rxd.initializer.has_initialized = False rxd.initializer.is_initializing = False - rxd.rxd.last_nrn_legacy_units = False rxd.rxd.free_conc_ptrs() rxd.rxd.free_curr_ptrs() rxd.rxd.rxd_include_node_flux1D(0, None, None, None) diff --git a/test/rxd/ecs/test_ecs_reinit.py b/test/rxd/ecs/test_ecs_reinit.py index 7b85fe48d5..5de8e36dfb 100644 --- a/test/rxd/ecs/test_ecs_reinit.py +++ b/test/rxd/ecs/test_ecs_reinit.py @@ -2,10 +2,10 @@ @pytest.fixture -def simple_model(neuron_instance): +def simple_model(neuron_nosave_instance): """A simple rxd model with species and extracellular regions.""" - h, rxd, data, save_path = neuron_instance + h, rxd, save_path = neuron_nosave_instance dend = h.Section(name="dend") dend.diam = 2 dend.nseg = 5 @@ -24,14 +24,14 @@ def simple_model(neuron_instance): paramB = rxd.Parameter([ecs], initial=0) decay = rxd.Rate(k, -0.1 * k) model = (dend, cyt, ecs, k, paramA, paramB, decay) - yield (neuron_instance, model) + yield (neuron_nosave_instance, model) def test_ecs_reinit(simple_model): """Test rxd.re_init updates extracellular node values from NEURON values""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, ecs, k, paramA, paramB, decay = model h.finitialize(-65) dend(0.2).ko = 0 @@ -44,8 +44,8 @@ def test_ecs_reinit_cvode(simple_model): """Test rxd.re_init updates extracellular node values from NEURON segments with CVode""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, ecs, k, paramA, paramB, decay = model h.CVode().active(True) h.finitialize(-65) diff --git a/test/rxd/test_currents.py b/test/rxd/test_currents.py index 6443190f5d..ae69b82804 100644 --- a/test/rxd/test_currents.py +++ b/test/rxd/test_currents.py @@ -63,10 +63,7 @@ def test_currents(model_pump): neuron_instance, model = model_pump h, rxd, data, save_path = neuron_instance - # check changing the units after initialization - h.nrnunit_use_legacy(False) h.finitialize(-65) - h.nrnunit_use_legacy(True) h.continuerun(10) if not save_path: max_err = compare_data(data) @@ -78,11 +75,8 @@ def test_currents_cvode(model_pump): neuron_instance, model = model_pump h, rxd, data, save_path = neuron_instance - # check changing the units after initialization h.CVode().active(True) - h.nrnunit_use_legacy(False) h.finitialize(-65) - h.nrnunit_use_legacy(True) h.continuerun(10) if not save_path: max_err = compare_data(data) diff --git a/test/rxd/test_reinit.py b/test/rxd/test_reinit.py index f8363f27c8..c9a08175cb 100644 --- a/test/rxd/test_reinit.py +++ b/test/rxd/test_reinit.py @@ -2,10 +2,10 @@ @pytest.fixture -def simple_model(neuron_instance): +def simple_model(neuron_nosave_instance): """A simple rxd model with species and regions and reactions.""" - h, rxd, data, save_path = neuron_instance + h, rxd, save_path = neuron_nosave_instance dend = h.Section(name="dend") dend.diam = 2 dend.nseg = 5 @@ -16,14 +16,14 @@ def simple_model(neuron_instance): paramB = rxd.Parameter([cyt], initial=0) decay = rxd.Rate(k, -0.1 * k) model = (dend, cyt, k, paramA, paramB, decay) - yield (neuron_instance, model) + yield (neuron_nosave_instance, model) def test_reinit(simple_model): """Test rxd.re_init updates node values from NEURON values""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, k, paramA, paramB, decay = model h.finitialize(-65) dend(0.5).ki = 0 @@ -34,8 +34,8 @@ def test_reinit(simple_model): def test_reinit_cvode(simple_model): """Test rxd.re_init updates node values from NEURON values with CVode""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, k, paramA, paramB, decay = model h.finitialize(-65) h.CVode().active(True) @@ -47,8 +47,8 @@ def test_reinit_cvode(simple_model): def test_reinit_3d(simple_model): """Test rxd.re_init updates node values from NEURON values in 3D""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, k, paramA, paramB, decay = model rxd.set_solve_type(dimension=3) # check changing the units after initialization @@ -63,8 +63,8 @@ def test_reinit_3d_cvode(simple_model): """Test rxd.re_init updates node values from NEURON values in 3D with CVode""" - neuron_instance, model = simple_model - h, rxd, data, save_path = neuron_instance + neuron_nosave_instance, model = simple_model + h, rxd, save_path = neuron_nosave_instance dend, cyt, k, paramA, paramB, decay = model rxd.set_solve_type(dimension=3) h.CVode().active(True) diff --git a/test/rxd/testdata b/test/rxd/testdata index e531eaa704..30c76babbb 160000 --- a/test/rxd/testdata +++ b/test/rxd/testdata @@ -1 +1 @@ -Subproject commit e531eaa704108fd1c880905484a28c15e5402e59 +Subproject commit 30c76babbbc2cff005fd3f6f649c8b81da41ee58