diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 587fda37e2..ae15e0428b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,6 +5,7 @@ concurrency: cancel-in-progress: true on: + merge_group: push: branches: - master @@ -65,7 +66,7 @@ jobs: ./configure --with-python-sys-prefix --prefix=$MUSIC_INSTALL_DIR --disable-anysource make -j install deactivate - working-directory: ${{runner.temp}} + working-directory: ${{runner.temp}} - name: Setup Xvfb run: | diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 962add64dc..d4206d7345 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -5,6 +5,7 @@ concurrency: cancel-in-progress: true on: + merge_group: push: branches: - master diff --git a/.github/workflows/external.yml b/.github/workflows/external.yml index 9b877be67b..088168c161 100644 --- a/.github/workflows/external.yml +++ b/.github/workflows/external.yml @@ -1,6 +1,6 @@ name: External CIs -concurrency: +concurrency: group: ${{ github.workflow }}#${{ github.ref }} cancel-in-progress: true @@ -10,7 +10,7 @@ on: env: PR_URL: ${{ github.event.pull_request.html_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + jobs: get-last-azure-url: runs-on: ubuntu-latest @@ -19,7 +19,7 @@ jobs: azure_drop_url: ${{ steps.drop.outputs.azure_drop_url }} pr_azure_sha: ${{ steps.drop.outputs.pr_azure_sha }} steps: - - id: drop + - id: drop run: | # use jq to get the last Azure drop URL from the PR and the SHA1 from the same body export pr_json=$(gh pr view $PR_URL --json comments -q 'last(.comments[] .body | capture(".*(?[0-9a-f]{40}).*?(?https://dev.azure.com/neuronsimulator/.*=zip)"))') @@ -32,7 +32,7 @@ jobs: export pr_azure_sha=$(echo $pr_json | jq -r .pr_azure_sha) echo azure_drop_url=$azure_drop_url >> $GITHUB_OUTPUT echo pr_azure_sha=$pr_azure_sha >> $GITHUB_OUTPUT - + - id: remove-label if: always() run: | @@ -47,7 +47,7 @@ jobs: env: pr_azure_sha: ${{ steps.drop.outputs.pr_azure_sha }} azure_drop_url: ${{ steps.drop.outputs.azure_drop_url }} - + nrn-modeldb-ci: needs: get-last-azure-url uses: neuronsimulator/nrn-modeldb-ci/.github/workflows/nrn-modeldb-ci.yaml@master @@ -56,7 +56,7 @@ jobs: neuron_v2: neuron-nightly pr-update: - needs: + needs: - nrn-modeldb-ci - get-last-azure-url runs-on: ubuntu-latest @@ -68,4 +68,3 @@ jobs: env: ARTIFACTS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} pr_azure_sha: ${{ needs.get-last-azure-url.outputs.pr_azure_sha }} - diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 1da74bbee4..1b490ed4b0 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -1,12 +1,13 @@ name: Check formatting -concurrency: +concurrency: group: ${{ github.workflow }}#${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: true on: + merge_group: push: - branches: + branches: - release/** pull_request: branches: diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 2fba4088ad..54c3777cea 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -1,12 +1,13 @@ name: NEURON CI -concurrency: +concurrency: group: ${{ github.workflow }}#${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: true on: + merge_group: push: - branches: + branches: # If nothing else, this is important for the ccache logic below... - master - release/** @@ -34,7 +35,7 @@ jobs: SDK_ROOT: $(xcrun --sdk macosx --show-sdk-path) SKIP_WHEELHOUSE_REPAIR: true BUILD_TYPE: Release - DESIRED_CMAKE_VERSION: 3.15 + 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' }} @@ -169,7 +170,7 @@ jobs: ./configure --with-python-sys-prefix --prefix=$MUSIC_INSTALL_DIR --disable-anysource make -j install deactivate - working-directory: ${{runner.temp}} + working-directory: ${{runner.temp}} - name: Register gcc problem matcher if: ${{matrix.config.flag_warnings == 'ON'}} @@ -195,7 +196,7 @@ jobs: repository: actions/cache ref: v3 path: tmp/actions/cache - + - name: Make actions/cache@v3 run even on failure run: | sed -i'.bak' -e '/ post-if: /d' tmp/actions/cache/action.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index f3d243e2ba..fd9dcc0771 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,10 +1,11 @@ name: Windows Installer -concurrency: +concurrency: group: ${{ github.workflow }}#${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: true on: + merge_group: workflow_call: inputs: tag: @@ -13,7 +14,7 @@ on: required: true type: string push: - branches: + branches: - master - release/** pull_request: @@ -54,12 +55,12 @@ jobs: .\nrn\ci\win_download_deps.cmd shell: powershell working-directory: ${{runner.workspace}} - + - name: Install Dependencies run: .\nrn\ci\win_install_deps.cmd shell: powershell working-directory: ${{runner.workspace}} - + - name: Build and Create Installer run: | rm.exe C:\WINDOWS\system32\bash.EXE diff --git a/CMakeLists.txt b/CMakeLists.txt index 01c9aa0cd2..2630543e6c 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}) @@ -484,6 +482,9 @@ if(NOT NRN_ENABLE_MPI_DYNAMIC OR ${num_mpi} EQUAL 1) set(NRN_INCLUDE_MPI_HEADERS ON) endif() +# initialize CLI11 submodule +cpp_cc_git_submodule(CLI11 BUILD PACKAGE CLI11 REQUIRED) + # ============================================================================= # Enable CoreNEURON support # ============================================================================= @@ -500,9 +501,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) @@ -512,9 +510,6 @@ if(NRN_ENABLE_CORENEURON) endif() set(CORENEURON_DIR ${PROJECT_SOURCE_DIR}/src/coreneuron) - # initialize CLI11 submodule - cpp_cc_git_submodule(CLI11 BUILD PACKAGE CLI11 REQUIRED) - add_subdirectory(${PROJECT_SOURCE_DIR}/src/coreneuron) # By default `nrnivmodl` should look for `nrnivmodl-core` in the NEURON install prefix. @@ -961,11 +956,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}") @@ -1036,9 +1026,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/MacroHelper.cmake b/cmake/MacroHelper.cmake index e5736389fd..60b5e72fd2 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -211,11 +211,11 @@ macro(nocmodl_mod_to_cpp modfile_basename) OUTPUT ${PROJECT_BINARY_DIR}/${modfile_basename}.cpp COMMAND ${CMAKE_COMMAND} -E env "MODLUNIT=${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib" - ${NRN_NOCMODL_SANITIZER_ENVIRONMENT} ${PROJECT_BINARY_DIR}/bin/nocmodl + ${NRN_NOCMODL_SANITIZER_ENVIRONMENT} $ ${PROJECT_SOURCE_DIR}/${modfile_basename}.mod COMMAND sed "'s/_reg()/_reg_()/'" ${PROJECT_SOURCE_DIR}/${modfile_basename}.cpp > ${PROJECT_BINARY_DIR}/${modfile_basename}.cpp - COMMAND rm ${PROJECT_SOURCE_DIR}/${modfile_basename}.cpp + COMMAND ${CMAKE_COMMAND} -E rm ${PROJECT_SOURCE_DIR}/${modfile_basename}.cpp DEPENDS nocmodl ${PROJECT_SOURCE_DIR}/${modfile_basename}.mod WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src/nrniv) endmacro() diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index fccabc873d..2b6ee3d1ee 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -427,7 +427,7 @@ set(NMODL_FILES_LIST units.cpp version.cpp) -set(IVOS_FILES_LIST listimpl.cpp string.cpp observe.cpp regexp.cpp resource.cpp) +set(IVOS_FILES_LIST listimpl.cpp observe.cpp regexp.cpp resource.cpp) set(MPI_DYNAMIC_INCLUDE nrnmpi_dynam.h nrnmpi_dynam_cinc nrnmpi_dynam_wrappers.inc) 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/README.md b/docs/README.md index eea5806b44..4e9f479312 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,23 +12,37 @@ Contents: ### Local build -#### Setup +#### Virtual environment It is recommended to use a Python virtual environment, for example: -``` +```bash python3 -m venv venv source venv/bin/activate ``` + In order to build documentation locally, you need to pip install the ``docs_requirements.txt`` : ``` pip3 install -r docs/docs_requirements.txt --upgrade ``` Also, make sure to have `Doxygen` and `pandoc` installed, and the dependencies listed in [conda_environment.yml](conda_environment.yml) -Note that this file is tailored to the ReadTheDocs setup, but lists all desired requirements. +Note that this conda environment file is tailored to the online ReadTheDocs setup (but it lists out all desired requirements, so make sure to check it out). + +#### Anaconda environment + +After installing Anaconda, create a new environment with the following command: + +```bash +conda env create --quiet --name rtd --file docs/conda_environment.yml +conda activate rtd +``` + +This will install all dependencies needed to build the documentation locally, in a similar way as on ReadTheDocs. However ReadTheDocs has a different setup, so it is of interest to head over and check the build logs for additional information. + +#### Confguring the build -With all dependencies installed, configure project with CMake as described in [CMake Build Options](./cmake_doc/options.rst#nrn-enable-docs-bool-off). +With all dependencies installed, configure project with CMake (>= v3.17) as described in [CMake Build Options](./cmake_doc/options.rst#nrn-enable-docs-bool-off). e.g. in your CMake build folder: 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/dev/hocdomain-sphinx.md b/docs/dev/hocdomain-sphinx.md new file mode 100644 index 0000000000..1fe0061327 --- /dev/null +++ b/docs/dev/hocdomain-sphinx.md @@ -0,0 +1,47 @@ +# HOC Sphinx Domain + +## Overview + +The HOC Sphinx Domain is a Sphinx extension that allows to document HOC constructs in Sphinx. +Given the extra effort to create a full-fledged domain, we've decided to hack it from the Python domain. +Ideally we'd have a proper HOC domain, but that is an extra workload and we lack the required knowledge to build one. +See https://github.com/neuronsimulator/nrn/issues/1540 + +## Hacking the Python Domain + +It is sometimes required to re-hack the domain to make it work with the latest version of Sphinx. +To that end, the following script can be used to generate the domain from the Python domain: + +```bash +cd docs +python3 generate_hocdomain.py +``` + +This script generates a HOC domain from the one available in the sphinx package and writes it to: + + docs/domains/hocdomain.py + +A comment is added at the top of the file to indicate that it is a generated file and the Sphinx version used to generate it. + + +## Sphinx Setup + +Like all Sphinx setup, the HOC Sphinx Domain is registered in ``docs/conf.py`` + +```python +# 1st step: make docs/domains available to Sphinx +sys.path.insert(0, os.path.abspath("./domains")) + +# .... + +# 2nd step: import hocdomain +import hocdomain # Sphinx HOC domain (hacked from the Python domain via docs/generate_hocdomain.py) + +# .... + +# 3rd step: setup the HOC domain in Sphinx +def setup(app): + # ... + # Set-up HOC domain + hocdomain.setup(app) +``` \ No newline at end of file diff --git a/docs/dev/index.rst b/docs/dev/index.rst index 6287935718..6838979739 100644 --- a/docs/dev/index.rst +++ b/docs/dev/index.rst @@ -9,3 +9,7 @@ NEURON Development topics data-structures.rst gpu-testing.rst workflow-code-paths.rst + ./setuptools/setuptools.md + ./morphology/morphology.md + hocdomain-sphinx.md + diff --git a/docs/dev/morphology/Import3D-hoc-morphio-backward.png b/docs/dev/morphology/Import3D-hoc-morphio-backward.png new file mode 100644 index 0000000000..9d5cfcd8e9 Binary files /dev/null and b/docs/dev/morphology/Import3D-hoc-morphio-backward.png differ diff --git a/docs/dev/morphology/Import3D-hoc.png b/docs/dev/morphology/Import3D-hoc.png new file mode 100644 index 0000000000..ced9f1e73e Binary files /dev/null and b/docs/dev/morphology/Import3D-hoc.png differ diff --git a/docs/dev/morphology/morphology.rst b/docs/dev/morphology/morphology.rst new file mode 100644 index 0000000000..1e4dd845eb --- /dev/null +++ b/docs/dev/morphology/morphology.rst @@ -0,0 +1,131 @@ +.. _morphology_loading: + +Morphology loading in NEURON +============================ + +Traditionally reading morphologies with NEURON has been coupled to the ``Import3D GUI`` tool. +The ``Import3D GUI`` tool is a graphical tool that allows the user to load a morphology and then interactively modify it. +:ref:`import3d_tutorial` provides a tutorial on how to use the ``Import3D GUI`` tool. + +The underlying implementation is mostly HOC and the GUI constructs can in principle be disregarded, since loading numerous morphologies for simulation does not make any use of them. +Note it is possible possible to load HOC-bound morphologies, but also Python-bound morphologies (refer to :ref:`bio_faq`). + +HOC Morphology Loading - Legacy Import3D_GUI +-------------------------------------------- + +A HOC ``CellType`` needs to be instantiated and the Import3D stack will be used to load the morphology. + +Please refer to `Cell.hoc from BlueBrain/neurodamus `_ for an example of HOC ``CellType``. + +.. image:: Import3D-hoc.png + +The ``instantiate`` method of Import3D stack will create a list of HOC commands that will be executed to load the morphology. + +Given a simple single point soma simple Neurolucida morphology :: + + ; This is the same morphology as simple.swc + ; + ; (0, 5) + ; (-5, 5)----- ------ (6, 5) + ; | + ; | + ; | + ; | Type = 3 + ; | + ; o origin + ; | + ; | Type = 2 + ; | + ; | + ;(-5, -4)----- ------ (6, -4) + ; (0, -4) + + + ("CellBody" + (Color Red) + (CellBody) + (0 0 0 2) + ) + + ((Dendrite) + (0 0 0 2) + (0 5 0 2) + ( + (-5 5 0 3) + | + (6 5 0 3) + ) + ) + + + ((Axon) + (0 0 0 2) + (0 -4 0 2) + ( + (6 -4 0 4) + | + (-5 -4 0 4) + ) + ) + +``instantiate`` will parse the file and create the following HOC commands +that will be executed in the HOC interpreter, thus loading the morphology: :: + + create soma[1] + forsec "soma" somatic.append + create axon[3] + forsec "axon" axonal.append + create dend[3] + forsec "dend" basal.append + forall all.append + soma { pt3dadd(1, 1.7484555e-07, 0, 1) } + soma { pt3dadd(0.94581723, -0.32469952, 0, 1) } + soma { pt3dadd(0.78914064, -0.61421257, 0, 1) } + soma { pt3dadd(0.54694813, -0.83716649, 0, 1) } + soma { pt3dadd(0.24548566, -0.96940023, 0, 1) } + soma { pt3dadd(-0.082579389, -0.99658448, 0, 1) } + soma { pt3dadd(-0.40169525, -0.91577339, 0, 1) } + soma { pt3dadd(-0.67728162, -0.73572391, 0, 1) } + soma { pt3dadd(-0.87947375, -0.47594735, 0, 1) } + soma { pt3dadd(-0.98636132, -0.16459456, 0, 1) } + soma { pt3dadd(-0.98636132, 0.16459462, 0, 1) } + soma { pt3dadd(-0.87947375, 0.47594741, 0, 1) } + soma { pt3dadd(-0.67728156, 0.73572391, 0, 1) } + soma { pt3dadd(-0.4016954, 0.91577333, 0, 1) } + soma { pt3dadd(-0.08257933, 0.99658448, 0, 1) } + soma { pt3dadd(0.2454855, 0.96940029, 0, 1) } + soma { pt3dadd(0.54694819, 0.83716649, 0, 1) } + soma { pt3dadd(0.78914052, 0.61421269, 0, 1) } + soma { pt3dadd(0.94581723, 0.32469946, 0, 1) } + soma { pt3dadd(1, 0, 0, 1) } + soma connect axon[0](0), 0.5 + axon[0] { pt3dadd(0, 0, 0, 2) } + axon[0] { pt3dadd(0, -4, 0, 2) } + axon[0] connect axon[1](0), 1 + axon[1] { pt3dadd(0, -4, 0, 2) } + axon[1] { pt3dadd(6, -4, 0, 4) } + axon[0] connect axon[2](0), 1 + axon[2] { pt3dadd(0, -4, 0, 2) } + axon[2] { pt3dadd(-5, -4, 0, 4) } + soma connect dend[0](0), 0.5 + dend[0] { pt3dadd(0, 0, 0, 2) } + dend[0] { pt3dadd(0, 5, 0, 2) } + dend[0] connect dend[1](0), 1 + dend[1] { pt3dadd(0, 5, 0, 2) } + dend[1] { pt3dadd(-5, 5, 0, 3) } + dend[0] connect dend[2](0), 1 + dend[2] { pt3dadd(0, 5, 0, 2) } + dend[2] { pt3dadd(6, 5, 0, 3) + + + +HOC Morphology Loading with MorphIO +----------------------------------- + +Given that legacy morphology loading is implemented in HOC, it does incur a performance penalty. +To that end, we are implementing a new mechanism for loading morphologies in NEURON, using the `MorphIO `_ library. + +The goal is to provide an API that will be backward compatible with the legacy mechanism, but will be implemented in C++ and will be more performant. +Ultimately, it would even be possible to remove the legacy mechanism, but that is not straightforward, as we need to couple it to the Import3D GUI/CellBuilder(see:ref:`cell_builder`). + +.. image:: Import3D-hoc-morphio-backward.png diff --git a/docs/dev/setuptools/images/setup-py.png b/docs/dev/setuptools/images/setup-py.png new file mode 100644 index 0000000000..2b6145637d Binary files /dev/null and b/docs/dev/setuptools/images/setup-py.png differ diff --git a/docs/dev/setuptools/setuptools.md b/docs/dev/setuptools/setuptools.md new file mode 100644 index 0000000000..56cc37f5e2 --- /dev/null +++ b/docs/dev/setuptools/setuptools.md @@ -0,0 +1,34 @@ +# setuptools + +## **setup.py** + +Traditionally **distutils** has been used, and **setuptools** ended up having its own internal copy. A lot of effort has been put into coping with the deprecation of **distutils** and accomodating **setuptools**. Furthermore, **setup.py** will also be discontinued and we will probably have to move on to **setuptools.build_meta** or find another way to package wheels and perform CMake builds. + + NEURON has several Python extensions +* HOC module (setuptools Extension with our CMake sauce on top) +* three Rx3D extensions (Cython extensions) +* MUSIC (Cython extension) + +## **Operational Modes** + +We use [setup.py](../../../setup.py) in two operational modes +: + +1) **wheel building** + It boils down to + + setup.py build_ext bdist_wheel + + We configure the HOC extension along with a CMake configure, build all extensios and collect them for the wheel. This is called via [build_wheels.bash](../../../packaging/python/build_wheels.bash). + +2) **CMake build** + It boils down to + + setup.py build_ext build + + We provide the cmake build folder, in this mode we do not run CMake configure, we build all extensions and make sure they are integrated into the CMake build and install. This is called via CMake in [src/nrnpython/CMakeLists.txt](../../../src/nrnpython/CMakeLists.txt) by passing **--cmake-build-dir** (the folder where we configured NEURON with CMake), along with other CMake options. + + +## **Activity Diagram** + +![](images/setup-py.png) \ No newline at end of file diff --git a/docs/guide/cellbuilder.rst b/docs/guide/cellbuilder.rst index ee0c56829f..99d4e97233 100644 --- a/docs/guide/cellbuilder.rst +++ b/docs/guide/cellbuilder.rst @@ -1,3 +1,5 @@ +.. _cell_builder: + Using the Cell Builder GUI ========================== 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/install/python_wheels.md b/docs/install/python_wheels.md index 01b8765e31..4eb0e7136f 100644 --- a/docs/install/python_wheels.md +++ b/docs/install/python_wheels.md @@ -271,3 +271,17 @@ The reason we are setting `SETUPTOOLS_SCM_PRETEND_VERSION` to a desired version ## Nightly wheels Nightly wheels get automatically published from `master` in CRON mode. + + +## How to test Azure wheels locally + +After retrieving the Azure drop URL (i.e. from the GitHub PR comment, or by going to Azure for a specific build): + +```bash +python3 -m pip wheel neuron-gpu-nightly --wheel-dir tmp --find-links 'https://dev.azure.com/neuronsimulator/aa1fb98d-a914-45c3-a215-5e5ef1bd7687/_apis/build/builds/7600/artifacts?artifactName=drop&api-version=7.0&%24format=zip' +``` +will download the wheel and its dependencies to `tmp/` and then you can test it with: + +```bash +./packaging/python/test_wheels.sh python3 ./tmp/NEURON_gpu_nightly-...whl true +``` \ No newline at end of file diff --git a/docs/install/windows.md b/docs/install/windows.md index 384a54a0c7..daf80e42b2 100644 --- a/docs/install/windows.md +++ b/docs/install/windows.md @@ -33,6 +33,43 @@ in order to: * install MPI * install MSYS2 (via `Chocolatey`) and then MinGW toolchain and required build pacakages +## Setting up Visual Studio Code + +It is highly recommended to use Visual Studio Code for development. You can install it from [https://code.visualstudio.com/](https://code.visualstudio.com/). + +During the development process, you will be using PowerShell, cmd and moreover MSYS2 MINGW64 shell. In order to be able to launch any of these in the IDE, add the following to `.vscode/setting.json` file in the root of the `nrn` repository: + +```json +{ + "cmake.configureOnOpen": false, + "terminal.integrated.profiles.windows": { + "PowerShell": { + "source": "PowerShell", + "icon": "terminal-powershell" + }, + "Command Prompt": { + "path": [ + "${env:windir}\\Sysnative\\cmd.exe", + "${env:windir}\\System32\\cmd.exe" + ], + "args": [], + "icon": "terminal-cmd" + }, + "MSYS2": { + "path": "C:\\msys64\\usr\\bin\\bash.exe", + "args": [ + "--login", + "-i" + ], + "env": { + "MSYSTEM": "MINGW64", + "CHERE_INVOKING": "1" + } + } + }, +} +``` + ## How to build NEURON For a complete `build/install/create setup.exe`, in a `MinGW64` shell you can run: @@ -64,3 +101,55 @@ make install make setup_exe ``` +Note that by default, the install path is `C:\nrn-install`. When building the installer via `setup_exe`, that is the path that will be used. + +## Troubleshooting + +### My PR is breaking the GitHub Windows CI + +You can use the `live-debug-win` PR tag. To enable it, you have to: + * add 'live-debug-win' to your PR title + * push something to your PR branch (note that just re-running the pipeline disregards the title update) + +This will setup an ssh session on `tmate.io` and you will get an MSYS2 shell to debug your feature. Be aware that this is limited to the MSYS2 environment. For more adapted debugging, you must set up a local Windows environment. + +### The installer is missing some files (includes, libraries, etc.) + +We ship out a minimal g++ compiler toolchain to allow nrnivmodl (mknrndll) to build nrnmech.dll. +This is handled by `mingw_files/nrnmingwenv.sh`. + +Points of interest: +* `cp_dlls()` -> ship all needed dlls by processing output of `cygcheck`. You can add more files to the caller list if needed. +* `copyinc()` -> ship all needed include files by processing output of `g++ -E`. You can add more files to the caller list if needed. +* `lib` paths for multiple versions of gcc. This is how you would handle it: + ```bash + gcclib=mingw64/lib/gcc/x86_64-w64-mingw32/$gccver # gcc 11.2.0 Rev 1 + if test -f /mingw64/lib/libgcc_s.a ; then # gcc 11.2.0 Rev 10 + gcclib=mingw64/lib + fi + copy $gcclib ' + libgcc_s.a + libstdc++.dll.a + ' + ``` + +### Windows CI has a new build failure without any code change + +GitHub/Azure runners are regularly updated. MSYS2 is already installed on the system with a specfic `pacman` cache at the time the runner images are built. As a consequence, some packages may not play well with the new environment. + +First line of attack is to compare successful and failed builds to see what changed. If the issue is related to a new package, one approach is to update the MSYS2 cache in `ci/win_install_deps.cmd` by uncommenting the following line: +```powershell +:: update pacman cache (sometimes required when new GH/Azure runner images are deployed) +:: %MSYS2_ROOT%\usr\bin\pacman -Syy +``` + +Downsides: +* slower CIs (more time to install new things from cache gradually over time) +* hit issues sooner rather than later (but then we can disable the cache update) + + +### association.hoc test failed + +Unfortunately there is not much we can do about it. This test is very very tricky to handle in the CI and it tests that `.hoc` files can be directly launched with the NEURON installation. We currently have a mitigation in place, we do it in two separate CI steps. Re-running the CI should fix the issue. + + 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/docs/python/visualization/plotshapeclass.rst b/docs/python/visualization/plotshapeclass.rst index d296126d0e..9715a705a4 100755 --- a/docs/python/visualization/plotshapeclass.rst +++ b/docs/python/visualization/plotshapeclass.rst @@ -172,6 +172,44 @@ PlotShape Description: Range variable (v, m_hh, etc.) to be used for time, space, and shape plots. + + Additionally, the variable can also be identified by species or specific region to show the corresponding voltage across. + + Example: + + .. code-block:: + python + + from neuron import h, rxd + from neuron.units import mM, µm, ms, mV + import plotly + h.load_file("stdrun.hoc") + + dend1 = h.Section('dend1') + dend2 = h.Section('dend2') + dend2.connect(dend1(1)) + + dend1.nseg = dend1.L = dend2.nseg = dend2.L = 11 + dend1.diam = dend2.diam = 2 * µm + + cyt = rxd.Region(dend1.wholetree(), nrn_region="i") + cyt2 = rxd.Region(dend2.wholetree(), nrn_region="i") + + ca = rxd.Species([cyt,cyt2], name="ca", charge=2, initial=0 * mM, d=1 * µm ** 2 / ms) + + ca.nodes(dend1(0.5))[0].include_flux(1e-13, units="mmol/ms") + + h.finitialize(-65 * mV) + h.continuerun(50 * ms) + + ps = h.PlotShape(False) + + ps.variable(ca[cyt]) + + ps.plot(plotly).show() + + + ---- diff --git a/external/coding-conventions b/external/coding-conventions index 3d157f9c8e..80a2c90134 160000 --- a/external/coding-conventions +++ b/external/coding-conventions @@ -1 +1 @@ -Subproject commit 3d157f9c8ea94d196a825aaa7f523265e360dc4b +Subproject commit 80a2c9013463b89b5c426e18403e9a2f87c59a00 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 53fa691f02..6bea87dc5f 100644 --- a/src/coreneuron/apps/main1.cpp +++ b/src/coreneuron/apps/main1.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -40,21 +41,17 @@ #include "coreneuron/network/partrans.hpp" #include "coreneuron/network/multisend.hpp" #include "coreneuron/io/nrn_setup.hpp" -#include "coreneuron/io/file_utils.hpp" #include "coreneuron/io/nrn2core_direct.h" #include "coreneuron/io/core2nrn_data_return.hpp" #include "coreneuron/utils/utils.hpp" +namespace fs = std::filesystem; + extern "C" { 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_)(); /** @@ -501,7 +498,7 @@ extern "C" int run_solve_core(int argc, char** argv) { // Create outpath if it does not exist if (nrnmpi_myid == 0) { - mkdir_p(corenrn_param.outpath.c_str()); + fs::create_directories(corenrn_param.outpath); } if (!corenrn_param.reportfilepath.empty()) { @@ -522,7 +519,7 @@ extern "C" int run_solve_core(int argc, char** argv) { std::string output_dir = corenrn_param.outpath; if (nrnmpi_myid == 0) { - mkdir_p(output_dir.c_str()); + fs::create_directories(output_dir); } #if NRNMPI if (corenrn_param.mpi_enable) { diff --git a/src/coreneuron/io/file_utils.cpp b/src/coreneuron/io/file_utils.cpp deleted file mode 100644 index 96ee47d2f3..0000000000 --- a/src/coreneuron/io/file_utils.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -# ============================================================================= -# Copyright (c) 2016 - 2021 Blue Brain Project/EPFL -# -# See top-level LICENSE file for details. -# ============================================================================= -*/ - -#include -#include -#include -#include -#include - -#if defined(MINGW) -#define mkdir(dir_name, permission) _mkdir(dir_name) -#endif - -/* adapted from : gist@jonathonreinhart/mkdir_p.c */ -int mkdir_p(const char* path) { - const int path_len = strlen(path); - if (path_len == 0) { - printf("Warning: Empty path for creating directory"); - return -1; - } - - char* dirpath = new char[path_len + 1]; - strcpy(dirpath, path); - errno = 0; - - /* iterate from outer upto inner dir */ - for (char* p = dirpath + 1; *p; p++) { - if (*p == '/') { - /* temporarily truncate to sub-dir */ - *p = '\0'; - - if (mkdir(dirpath, S_IRWXU) != 0) { - if (errno != EEXIST) - return -1; - } - *p = '/'; - } - } - - if (mkdir(dirpath, S_IRWXU) != 0) { - if (errno != EEXIST) { - return -1; - } - } - - delete[] dirpath; - return 0; -} diff --git a/src/coreneuron/io/file_utils.hpp b/src/coreneuron/io/file_utils.hpp deleted file mode 100644 index 1ce2eab838..0000000000 --- a/src/coreneuron/io/file_utils.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/* -# ============================================================================= -# Copyright (c) 2016 - 2021 Blue Brain Project/EPFL -# -# See top-level LICENSE file for details. -# ============================================================================= -*/ - -/** - * @file file_utils.h - * @brief Utility functions for file/directory management - * - */ - -#pragma once - -/** @brief Creates directory if doesn't exisit (similar to mkdir -p) - * @param Directory path - * @return Status - */ -int mkdir_p(const char* path); 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/io/nrn_checkpoint.cpp b/src/coreneuron/io/nrn_checkpoint.cpp index 29e9deb777..77e301b4e5 100644 --- a/src/coreneuron/io/nrn_checkpoint.cpp +++ b/src/coreneuron/io/nrn_checkpoint.cpp @@ -5,6 +5,7 @@ # See top-level LICENSE file for details. # =============================================================================. */ +#include #include #include #include @@ -19,13 +20,14 @@ #include "coreneuron/network/netpar.hpp" #include "coreneuron/utils/vrecitem.h" #include "coreneuron/mechanism/mech/mod2c_core_thread.hpp" -#include "coreneuron/io/file_utils.hpp" #include "coreneuron/permute/data_layout.hpp" #include "coreneuron/permute/node_permute.h" #include "coreneuron/coreneuron.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" #include "coreneuron/apps/corenrn_parameters.hpp" +namespace fs = std::filesystem; + namespace coreneuron { // Those functions comes from mod file directly extern int checkpoint_save_patternstim(_threadargsproto_); @@ -37,7 +39,7 @@ CheckPoints::CheckPoints(const std::string& save, const std::string& restore) , restored(false) { if (!save.empty()) { if (nrnmpi_myid == 0) { - mkdir_p(save.c_str()); + fs::create_directories(save); } } } diff --git a/src/coreneuron/mechanism/capac.cpp b/src/coreneuron/mechanism/capac.cpp index f47a4ebd77..b6454377b6 100644 --- a/src/coreneuron/mechanism/capac.cpp +++ b/src/coreneuron/mechanism/capac.cpp @@ -15,7 +15,7 @@ #define _PRAGMA_FOR_INIT_ACC_LOOP_ \ nrn_pragma_acc(parallel loop present(vdata [0:_cntml_padded * nparm]) if (_nt->compute_gpu)) \ nrn_pragma_omp(target teams distribute parallel for simd if(_nt->compute_gpu)) -#define _STRIDE _cntml_padded + _iml +#define CNRN_FLAT_INDEX_IML_ROW(i) ((i) * (_cntml_padded) + (_iml)) namespace coreneuron { @@ -45,8 +45,8 @@ void capacitance_reg(void) { hoc_register_prop_size(mechtype, nparm, 0); } -#define cm vdata[0 * _STRIDE] -#define i_cap vdata[1 * _STRIDE] +#define cm vdata[CNRN_FLAT_INDEX_IML_ROW(0)] +#define i_cap vdata[CNRN_FLAT_INDEX_IML_ROW(1)] /* cj is analogous to 1/dt for cvode and daspk diff --git a/src/coreneuron/mechanism/eion.cpp b/src/coreneuron/mechanism/eion.cpp index fb95ae21bb..d0f5e01a0c 100644 --- a/src/coreneuron/mechanism/eion.cpp +++ b/src/coreneuron/mechanism/eion.cpp @@ -18,7 +18,7 @@ #include "coreneuron/permute/data_layout.hpp" #include "coreneuron/utils/nrnoc_aux.hpp" -#define _STRIDE _cntml_padded + _iml +#define CNRN_FLAT_INDEX_IML_ROW(i) ((i) * (_cntml_padded) + (_iml)) namespace coreneuron { @@ -142,11 +142,11 @@ the USEION statement of any model using this ion\n", } #if VECTORIZE -#define erev pd[0 * _STRIDE] /* From Eion */ -#define conci pd[1 * _STRIDE] -#define conco pd[2 * _STRIDE] -#define cur pd[3 * _STRIDE] -#define dcurdv pd[4 * _STRIDE] +#define erev pd[CNRN_FLAT_INDEX_IML_ROW(0)] /* From Eion */ +#define conci pd[CNRN_FLAT_INDEX_IML_ROW(1)] +#define conco pd[CNRN_FLAT_INDEX_IML_ROW(2)] +#define cur pd[CNRN_FLAT_INDEX_IML_ROW(3)] +#define dcurdv pd[CNRN_FLAT_INDEX_IML_ROW(4)] /* handle erev, conci, conc0 "in the right way" according to ion_style diff --git a/src/coreneuron/mechanism/mech/mod2c_core_thread.hpp b/src/coreneuron/mechanism/mech/mod2c_core_thread.hpp index d18160f3a7..1615d20bd2 100644 --- a/src/coreneuron/mechanism/mech/mod2c_core_thread.hpp +++ b/src/coreneuron/mechanism/mech/mod2c_core_thread.hpp @@ -14,7 +14,7 @@ namespace coreneuron { -#define _STRIDE _cntml_padded + _iml +#define CNRN_FLAT_INDEX_IML_ROW(i) ((i) * (_cntml_padded) + (_iml)) #define _threadargscomma_ _iml, _cntml_padded, _p, _ppvar, _thread, _nt, _ml, _v, #define _threadargsprotocomma_ \ @@ -77,7 +77,7 @@ int euler_thread(int neqn, int* var, int* der, F fun, _threadargsproto_) { fun(_threadargs_); // std::invoke in C++17 /* update dependent variables */ for (int i = 0; i < neqn; i++) { - _p[var[i] * _STRIDE] += dt * (_p[der[i] * _STRIDE]); + _p[CNRN_FLAT_INDEX_IML_ROW(var[i])] += dt * (_p[CNRN_FLAT_INDEX_IML_ROW(der[i])]); } return 0; } diff --git a/src/coreneuron/mpi/lib/mpispike.cpp b/src/coreneuron/mpi/lib/mpispike.cpp index bbe81ac6c2..b7c1bcf1bf 100644 --- a/src/coreneuron/mpi/lib/mpispike.cpp +++ b/src/coreneuron/mpi/lib/mpispike.cpp @@ -289,46 +289,30 @@ void nrnmpi_barrier_impl() { MPI_Barrier(nrnmpi_comm); } -double nrnmpi_dbl_allreduce_impl(double x, int type) { - double result; - MPI_Op tt; +static MPI_Op type2OP(int type) { if (type == 1) { - tt = MPI_SUM; + return MPI_SUM; } else if (type == 2) { - tt = MPI_MAX; + return MPI_MAX; } else { - tt = MPI_MIN; + return MPI_MIN; } - MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, tt, nrnmpi_comm); +} + +double nrnmpi_dbl_allreduce_impl(double x, int type) { + double result; + MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, type2OP(type), nrnmpi_comm); return result; } void nrnmpi_dbl_allreduce_vec_impl(double* src, double* dest, int cnt, int type) { - MPI_Op tt; assert(src != dest); - if (type == 1) { - tt = MPI_SUM; - } else if (type == 2) { - tt = MPI_MAX; - } else { - tt = MPI_MIN; - } - MPI_Allreduce(src, dest, cnt, MPI_DOUBLE, tt, nrnmpi_comm); - return; + MPI_Allreduce(src, dest, cnt, MPI_DOUBLE, type2OP(type), nrnmpi_comm); } void nrnmpi_long_allreduce_vec_impl(long* src, long* dest, int cnt, int type) { - MPI_Op tt; assert(src != dest); - if (type == 1) { - tt = MPI_SUM; - } else if (type == 2) { - tt = MPI_MAX; - } else { - tt = MPI_MIN; - } - MPI_Allreduce(src, dest, cnt, MPI_LONG, tt, nrnmpi_comm); - return; + MPI_Allreduce(src, dest, cnt, MPI_LONG, type2OP(type), nrnmpi_comm); } #if NRN_MULTISEND diff --git a/src/coreneuron/sim/scopmath/crout_thread.hpp b/src/coreneuron/sim/scopmath/crout_thread.hpp index 3ac9c66f2c..fec10fe9b7 100644 --- a/src/coreneuron/sim/scopmath/crout_thread.hpp +++ b/src/coreneuron/sim/scopmath/crout_thread.hpp @@ -18,8 +18,8 @@ namespace coreneuron { #error "naming clash on crout_thread.hpp-internal macros" #endif #define scopmath_crout_b(arg) b[scopmath_crout_ix(arg)] -#define scopmath_crout_ix(arg) ((arg) *_STRIDE) -#define scopmath_crout_y(arg) _p[y[arg] * _STRIDE] +#define scopmath_crout_ix(arg) CNRN_FLAT_INDEX_IML_ROW(arg) +#define scopmath_crout_y(arg) _p[CNRN_FLAT_INDEX_IML_ROW(y[arg])] /** * Performs an LU triangular factorization of a real matrix by the Crout diff --git a/src/coreneuron/sim/scopmath/newton_thread.hpp b/src/coreneuron/sim/scopmath/newton_thread.hpp index dc70b643ae..44076c986a 100644 --- a/src/coreneuron/sim/scopmath/newton_thread.hpp +++ b/src/coreneuron/sim/scopmath/newton_thread.hpp @@ -21,9 +21,9 @@ namespace coreneuron { #if defined(scopmath_newton_ix) || defined(scopmath_newton_s) || defined(scopmath_newton_x) #error "naming clash on newton_thread.hpp-internal macros" #endif -#define scopmath_newton_ix(arg) ((arg) *_STRIDE) -#define scopmath_newton_s(arg) _p[s[arg] * _STRIDE] -#define scopmath_newton_x(arg) _p[(arg) *_STRIDE] +#define scopmath_newton_ix(arg) CNRN_FLAT_INDEX_IML_ROW(arg) +#define scopmath_newton_s(arg) _p[CNRN_FLAT_INDEX_IML_ROW(s[arg])] +#define scopmath_newton_x(arg) _p[CNRN_FLAT_INDEX_IML_ROW(arg)] namespace detail { /** * @brief Calculate the Jacobian matrix using finite central differences. diff --git a/src/coreneuron/sim/scopmath/sparse_thread.hpp b/src/coreneuron/sim/scopmath/sparse_thread.hpp index 8d84cbb0e8..71978197fe 100644 --- a/src/coreneuron/sim/scopmath/sparse_thread.hpp +++ b/src/coreneuron/sim/scopmath/sparse_thread.hpp @@ -436,7 +436,7 @@ inline void init_coef_list(SparseObj* so, int _iml) { defined(scopmath_sparse_x) #error "naming clash on sparse_thread.hpp-internal macros" #endif -#define scopmath_sparse_ix(arg) ((arg) *_STRIDE) +#define scopmath_sparse_ix(arg) CNRN_FLAT_INDEX_IML_ROW(arg) inline void subrow(SparseObj* so, Elm* pivot, Elm* rowsub, int _iml) { unsigned int const _cntml_padded{so->_cntml_padded}; double const r{rowsub->value[_iml] / pivot->value[_iml]}; @@ -602,7 +602,7 @@ int sparse_thread(SparseObj* so, #undef scopmath_sparse_d #undef scopmath_sparse_ix #undef scopmath_sparse_s -#define scopmath_sparse_x(arg) _p[x[arg] * _STRIDE] +#define scopmath_sparse_x(arg) _p[CNRN_FLAT_INDEX_IML_ROW(x[arg])] /* for solving ax=b */ template int _cvode_sparse_thread(void** vpr, int n, int* x, SPFUN fun, _threadargsproto_) { diff --git a/src/coreneuron/sim/scopmath/ssimplic_thread.hpp b/src/coreneuron/sim/scopmath/ssimplic_thread.hpp index cd341a6274..4b31dc4706 100644 --- a/src/coreneuron/sim/scopmath/ssimplic_thread.hpp +++ b/src/coreneuron/sim/scopmath/ssimplic_thread.hpp @@ -13,7 +13,7 @@ namespace coreneuron { #if defined(scopmath_ssimplic_s) #error "naming clash on ssimplic_thread.hpp-internal macros" #endif -#define scopmath_ssimplic_s(arg) _p[s[arg] * _STRIDE] +#define scopmath_ssimplic_s(arg) _p[CNRN_FLAT_INDEX_IML_ROW(s[arg])] static int check_state(int n, int* s, _threadargsproto_) { bool flag{true}; for (int i = 0; i < n; i++) { 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/ivoc/apwindow.cpp b/src/ivoc/apwindow.cpp index e4733b7827..71c07bcf36 100644 --- a/src/ivoc/apwindow.cpp +++ b/src/ivoc/apwindow.cpp @@ -452,7 +452,7 @@ void PrintableWindow::type(const char* s) { type_ = s; } const char* PrintableWindow::type() const { - return type_.string(); + return type_.c_str(); } // StandardWindow diff --git a/src/ivoc/apwindow.h b/src/ivoc/apwindow.h index a478212f86..5c173056a0 100644 --- a/src/ivoc/apwindow.h +++ b/src/ivoc/apwindow.h @@ -1,6 +1,8 @@ #ifndef dismiswin_h #define dismiswin_h +#include + #include #include @@ -103,7 +105,7 @@ class PrintableWindow: public DismissableWindow, public Observable { virtual void default_geometry(); private: - CopyString type_; + std::string type_; static OcGlyphContainer* intercept_; bool mappable_; bool xplace_; diff --git a/src/ivoc/datapath.cpp b/src/ivoc/datapath.cpp index eba19af7ba..b7c65cdcdf 100644 --- a/src/ivoc/datapath.cpp +++ b/src/ivoc/datapath.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "hoclist.h" #if HAVE_IV @@ -22,24 +21,16 @@ extern Objectdata* hoc_top_level_data; /*static*/ class PathValue { public: PathValue(); - ~PathValue(); - CopyString* path; + ~PathValue() = default; + std::string path{}; Symbol* sym; double original; char* str; }; PathValue::PathValue() { - path = NULL; str = NULL; sym = NULL; } -PathValue::~PathValue() { - if (path) { - delete path; - } -} - -using StringList = std::vector; class HocDataPathImpl { private: @@ -62,7 +53,7 @@ class HocDataPathImpl { private: std::map table_; - StringList strlist_; + std::vector strlist_; int size_, count_, found_so_far_; int pathstyle_; }; @@ -110,14 +101,14 @@ void HocDataPaths::search() { } } -String* HocDataPaths::retrieve(double* pd) const { +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 nullptr; + return {}; } Symbol* HocDataPaths::retrieve_sym(double* pd) const { @@ -139,13 +130,13 @@ void HocDataPaths::append(char** pd) { } } -String* HocDataPaths::retrieve(char** pd) const { +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 nullptr; + return {}; } /*------------------------------*/ @@ -205,20 +196,20 @@ PathValue* HocDataPathImpl::found_v(void* v, const char* buf, Symbol* sym) { PathValue* pv; if (pathstyle_ != 2) { char path[500]; - CopyString cs(""); + std::string cs{}; for (const auto& str: strlist_) { - Sprintf(path, "%s%s.", cs.string(), str); + Sprintf(path, "%s%s.", cs.c_str(), str.c_str()); cs = path; } - Sprintf(path, "%s%s", cs.string(), buf); + 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) { - pv->path = new CopyString(path); + if (pv->path.empty()) { + pv->path = path; pv->sym = sym; ++found_so_far_; } @@ -258,7 +249,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { Symbol* sym; int i, total; char buf[200]; - CopyString cs(""); + std::string cs{}; if (sl) for (sym = sl->first; sym; sym = sym->next) { if (sym->cpublic != 2) { @@ -278,7 +269,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { if (pd[i] == sentinal) { Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); cs = buf; - found(pd + i, cs.string(), sym); + found(pd + i, cs.c_str(), sym); } } } break; @@ -287,7 +278,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { if (*pstr == NULL) { Sprintf(buf, "%s", sym->name); cs = buf; - found(pstr, cs.string(), sym); + found(pstr, cs.c_str(), sym); } } break; case OBJECTVAR: { @@ -304,7 +295,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { if (obp[i]->u.dataspace != od) { Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); cs = buf; - strlist_.push_back((char*) cs.string()); + strlist_.push_back(cs); obp[i]->recurse = 1; search(obp[i]->u.dataspace, obp[i]->ctemplate->symtable); obp[i]->recurse = 0; @@ -315,7 +306,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { if (t->is_point_) { Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); cs = buf; - strlist_.push_back((char*) cs.string()); + strlist_.push_back(cs); search((Point_process*) obp[i]->u.this_pointer, sym); strlist_.pop_back(); } @@ -330,7 +321,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { if (pitm[i]) { Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od)); cs = buf; - strlist_.push_back((char*) cs.string()); + strlist_.push_back(cs); search(hocSEC(pitm[i])); strlist_.pop_back(); } @@ -343,7 +334,7 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { Object* obj = OBJ(q); Sprintf(buf, "%s[%d]", sym->name, obj->index); cs = buf; - strlist_.push_back((char*) cs.string()); + strlist_.push_back(cs); if (!t->constructor) { search(obj->u.dataspace, t->symtable); } else { @@ -361,14 +352,14 @@ void HocDataPathImpl::search(Objectdata* od, Symlist* sl) { void HocDataPathImpl::search_vectors() { char buf[200]; - CopyString cs(""); + 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((char*) cs.string()); + strlist_.push_back(cs); Vect* vec = (Vect*) obj->u.this_pointer; int size = vec->size(); double* pd = vector_vec(vec); @@ -384,14 +375,14 @@ void HocDataPathImpl::search_vectors() { void HocDataPathImpl::search_pysec() { #if USE_PYTHON - CopyString cs(""); + 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((char*) cs.string()); + strlist_.push_back(cs); search(sec); strlist_.pop_back(); } @@ -418,7 +409,6 @@ void HocDataPathImpl::search(Section* sec) { } void HocDataPathImpl::search(Node* nd, double x) { char buf[100]; - CopyString cs(""); if (NODEV(nd) == sentinal) { Sprintf(buf, "v(%g)", x); // the conversion below yields a pointer that is potentially invalidated diff --git a/src/ivoc/datapath.h b/src/ivoc/datapath.h index 1e8d96920a..0f88d6e6d4 100644 --- a/src/ivoc/datapath.h +++ b/src/ivoc/datapath.h @@ -15,8 +15,8 @@ class HocDataPaths { void append(double*); void append(char**); void search(); - String* retrieve(double*) const; - String* retrieve(char**) const; + std::string retrieve(double*) const; + std::string retrieve(char**) const; Symbol* retrieve_sym(double*) const; int style(); diff --git a/src/ivoc/graph.cpp b/src/ivoc/graph.cpp index b073a0f350..3868bc0707 100644 --- a/src/ivoc/graph.cpp +++ b/src/ivoc/graph.cpp @@ -1369,7 +1369,6 @@ Graph::Graph(bool b) loc_ = 0; x_expr_ = NULL; x_pval_ = {}; - var_name_ = NULL; rvp_ = NULL; cross_action_ = NULL; vector_copy_ = false; @@ -1463,20 +1462,13 @@ Graph::~Graph() { Resource::unref(sc_); Resource::unref(current_polyline_); Resource::unref(family_label_); - if (var_name_) { - delete var_name_; - } if (cross_action_) { delete cross_action_; } } void Graph::name(char* s) { - if (var_name_) { - *var_name_ = s; - } else { - var_name_ = new CopyString(s); - } + var_name_ = s; } void Graph::help() { @@ -2363,14 +2355,14 @@ void Graph::save_phase2(std::ostream& o) { Sprintf(buf, "save_window_.family(\"%s\")", family_label_->text()); o << buf << std::endl; } - if (var_name_) { - if ((var_name_->string())[var_name_->length() - 1] == '.') { - Sprintf(buf, "%sappend(save_window_)", var_name_->string()); + if (!var_name_.empty()) { + if (var_name_.back() == '.') { + Sprintf(buf, "%sappend(save_window_)", var_name_.c_str()); } else { - Sprintf(buf, "%s = save_window_", var_name_->string()); + Sprintf(buf, "%s = save_window_", var_name_.c_str()); } o << buf << std::endl; - Sprintf(buf, "save_window_.save_name(\"%s\")", var_name_->string()); + Sprintf(buf, "save_window_.save_name(\"%s\")", var_name_.c_str()); o << buf << std::endl; } if (x_expr_) { @@ -2429,7 +2421,7 @@ void Graph::choose_sym() { neuron::container::data_handle pd_handle{pd}; if (sc_->selected_vector_count()) { - Sprintf(buf, "%s", sc_->selected()->string()); + Sprintf(buf, "%s", sc_->selected().c_str()); GraphVector* gv = new GraphVector(buf); gv->color(color()); gv->brush(brush()); @@ -2444,19 +2436,19 @@ void Graph::choose_sym() { flush(); break; } else if (pd) { - add_var(sc_->selected()->string(), color(), brush(), 1, 2); + add_var(sc_->selected().c_str(), color(), brush(), 1, 2); break; } else { - CopyString s(*sc_->selected()); + auto s = sc_->selected(); // above required due to bug in mswindows version in which // sc_->selected seems volatile under some kinds of hoc // executions. - Sprintf(buf, "hoc_ac_ = %s\n", s.string()); + Sprintf(buf, "hoc_ac_ = %s\n", s.c_str()); if (oc.run(buf) == 0) { - add_var(s.string(), color(), brush(), 0, 2); + add_var(s.c_str(), color(), brush(), 0, 2); break; } - hoc_warning(s.string(), "is not an expression."); + hoc_warning(s.c_str(), "is not an expression."); } } // sc_->unref(); @@ -2475,12 +2467,12 @@ void Graph::family_label_chooser() { } while (fsc_->post_for_aligned(XYView::current_pick_view()->canvas()->window(), .5, 1.)) { char buf[256]; - Sprintf(buf, "hoc_ac_ = %s\n", fsc_->selected()->string()); + Sprintf(buf, "hoc_ac_ = %s\n", fsc_->selected().c_str()); if (oc.run(buf) == 0) { - family(fsc_->selected()->string()); + family(fsc_->selected().c_str()); break; } - hoc_warning(sc_->selected()->string(), "is not an expression."); + hoc_warning(sc_->selected().c_str(), "is not an expression."); } } @@ -3010,7 +3002,7 @@ GLabel::~GLabel() { } Glyph* GLabel::clone() const { - return new GLabel(text_.string(), color_, fixtype_, scale_, x_align_, y_align_); + return new GLabel(text_.c_str(), color_, fixtype_, scale_, x_align_, y_align_); } void GLabel::save(std::ostream& o, Coord x, Coord y) { @@ -3022,7 +3014,7 @@ void GLabel::save(std::ostream& o, Coord x, Coord y) { "save_window_.label(%g, %g, \"%s\", %d, %g, %g, %g, %d)", x, y, - text_.string(), + text_.c_str(), fixtype_, scale_, x_align_, @@ -3050,7 +3042,7 @@ void GLabel::align(float x, float y) { void GLabel::color(const Color* c) { Resource::unref(label_); WidgetKit& kit = *WidgetKit::instance(); - label_ = new Label(text_, kit.font(), c); + label_ = new Label(text_.c_str(), kit.font(), c); label_->ref(); Resource::ref(c); Resource::unref(color_); @@ -3064,7 +3056,7 @@ void GLabel::text(const char* t) { Resource::unref(label_); WidgetKit& kit = *WidgetKit::instance(); text_ = t; - label_ = new Label(text_, kit.font(), color_); + label_ = new Label(text_.c_str(), kit.font(), color_); label_->ref(); } @@ -3106,7 +3098,7 @@ void GLabel::draw(Canvas* c, const Allocation& a1) const { // printf("transformer %g %g %g %g %g %g\n", a00, a01, a10, a11, a20, a21); label_->draw(c, a2); c->pop_transform(); - IfIdraw(text(c, text_.string(), t, NULL, color())); + IfIdraw(text(c, text_.c_str(), t, NULL, color())); } // DataVec------------------ @@ -3288,7 +3280,7 @@ GraphVector::~GraphVector() { } const char* GraphVector::name() const { - return name_.string(); + return name_.c_str(); } void GraphVector::save(std::ostream&) {} diff --git a/src/ivoc/graph.h b/src/ivoc/graph.h index 69b2b7b48f..72e58b5874 100644 --- a/src/ivoc/graph.h +++ b/src/ivoc/graph.h @@ -170,7 +170,7 @@ class Graph: public Scene { // Scene of GraphLines labels and polylines bool extension_flushed_; SymChooser* sc_; static SymChooser* fsc_; - CopyString* var_name_; + std::string var_name_; GPolyLine* current_polyline_; const Color* color_; @@ -396,7 +396,7 @@ class GraphVector: public GPolyLine, public Observer { // fixed x and vector of private: DataPointers* dp_; - CopyString name_; + std::string name_; bool disconnect_defer_; }; @@ -447,7 +447,7 @@ class GLabel: public Glyph { return scale_; } const char* text() const { - return text_.string(); + return text_.c_str(); } int fixtype() const { return fixtype_; @@ -480,7 +480,7 @@ class GLabel: public Glyph { int fixtype_; float scale_; float x_align_, y_align_; - CopyString text_; + std::string text_; Glyph* label_; const Color* color_; GPolyLine* gpl_; diff --git a/src/ivoc/ivocmain.cpp b/src/ivoc/ivocmain.cpp index 43c1bc4709..315a375eda 100644 --- a/src/ivoc/ivocmain.cpp +++ b/src/ivoc/ivocmain.cpp @@ -33,7 +33,6 @@ void iv_display_scale(float); #include "idraw.h" #include #endif -#include #include "string.h" #include "oc2iv.h" #include "nrnmpi.h" @@ -654,8 +653,8 @@ int ivocmain_session(int argc, const char** argv, const char** env, int start_se nrn_optarg_on("-mpi", &our_argc, our_argv); #if (defined(NRNMECH_DLL_STYLE) || defined(WIN32)) - String str; #if HAVE_IV + String str; if (session) { if (session->style()->find_attribute("nrnmechdll", str)) { nrn_mech_dll = str.string(); diff --git a/src/ivoc/nrnsymdiritem.h b/src/ivoc/nrnsymdiritem.h index 6f395aacad..7a88be6c56 100644 --- a/src/ivoc/nrnsymdiritem.h +++ b/src/ivoc/nrnsymdiritem.h @@ -4,7 +4,6 @@ // allow communication between src/ivoc/symdir.cpp and src/nrniv/pysecname.cpp #include -#include class SymbolItem { public: @@ -19,7 +18,7 @@ class SymbolItem { return ob_; } void no_object(); - const String& name() const { + const std::string& name() const { return name_; } bool is_directory() const; @@ -30,7 +29,7 @@ class SymbolItem { int pysec_type_; /* PYSECOBJ (cell prefix) or PYSECNAME (Section) */ void* pysec_; /* Name2Section* or Section* */ private: - CopyString name_; + std::string name_; Symbol* symbol_; int index_; Object* ob_; diff --git a/src/ivoc/objcmd.cpp b/src/ivoc/objcmd.cpp index 92384c1636..9b30de6fa1 100644 --- a/src/ivoc/objcmd.cpp +++ b/src/ivoc/objcmd.cpp @@ -31,12 +31,11 @@ HocCommand::HocCommand(Object* pobj) { } po_ = pobj; hoc_obj_ref(po_); - s_ = NULL; obj_ = NULL; } void HocCommand::init(const char* cmd, Object* obj) { - s_ = new CopyString(cmd); + s_ = std::make_unique(cmd); obj_ = obj; po_ = NULL; if (obj_) { @@ -46,17 +45,13 @@ void HocCommand::init(const char* cmd, Object* obj) { void HocCommand::update(Observable*) { // obj_ has been freed obj_ = NULL; - delete s_; - s_ = new CopyString(""); + s_ = std::make_unique(""); } HocCommand::~HocCommand() { if (obj_) { nrn_notify_pointer_disconnect(this); } - if (s_) { - delete s_; - } if (po_) { hoc_obj_unref(po_); } @@ -66,9 +61,9 @@ void HocCommand::help() { #if HAVE_IV char buf[200]; if (obj_) { - Sprintf(buf, "%s %s", s_->string(), obj_->ctemplate->sym->name); + Sprintf(buf, "%s %s", s_->c_str(), obj_->ctemplate->sym->name); } else { - Sprintf(buf, "%s", s_->string()); + Sprintf(buf, "%s", s_->c_str()); } Oc::help(buf); #endif @@ -77,7 +72,7 @@ void HocCommand::help() { const char* ccc = "PythonObject"; const char* HocCommand::name() { if (po_ == NULL) { - return s_->string(); + return s_->c_str(); } else { return ccc; } @@ -106,7 +101,7 @@ int HocCommand::execute(bool notify) { return 0; } char buf[256]; - Sprintf(buf, "{%s}\n", s_->string()); + Sprintf(buf, "{%s}\n", s_->c_str()); err = hoc_obj_run(buf, obj_); } #if HAVE_IV diff --git a/src/ivoc/objcmd.h b/src/ivoc/objcmd.h index b3bfd1985e..bb54aefa51 100644 --- a/src/ivoc/objcmd.h +++ b/src/ivoc/objcmd.h @@ -1,7 +1,8 @@ #ifndef objcmd_h #define objcmd_h -#include +#include + #include #if HAVE_IV #include @@ -39,7 +40,7 @@ class HocCommand: public Observer { private: Object* obj_; - CopyString* s_; + std::unique_ptr s_{}; Object* po_; }; diff --git a/src/ivoc/ocfile.cpp b/src/ivoc/ocfile.cpp index bf7cca386e..ee5b24da7b 100644 --- a/src/ivoc/ocfile.cpp +++ b/src/ivoc/ocfile.cpp @@ -311,7 +311,7 @@ void OcFile::close() { } void OcFile::set_name(const char* s) { close(); - if (s != filename_.string()) { + if (s != filename_.c_str()) { filename_ = s; } } @@ -329,7 +329,7 @@ void OcFile::binary_mode() { // printf("can't switch to binary mode. No setmode\n"); mode_[1] = 'b'; mode_[2] = '\0'; - file_ = freopen(filename_.string(), mode_, file()); + file_ = freopen(filename_.c_str(), mode_, file()); #else setmode(fileno(file()), O_BINARY); #endif @@ -471,13 +471,13 @@ void OcFile::file_chooser_style(const char* type, const char* OcFile::dir() { #if HAVE_IV if (fc_) { - dirname_ = *fc_->dir(); + dirname_ = *fc_->dir()->string(); } else #endif { dirname_ = ""; } - return dirname_.string(); + return dirname_.c_str(); } bool OcFile::file_chooser_popup() { diff --git a/src/ivoc/ocfile.h b/src/ivoc/ocfile.h index f7269adcbb..046fe083fc 100644 --- a/src/ivoc/ocfile.h +++ b/src/ivoc/ocfile.h @@ -1,7 +1,6 @@ #ifndef ocfile_h #define ocfile_h -#include #include class File; class FileChooser; @@ -13,7 +12,7 @@ class OcFile { bool open(const char* filename, const char* type); void set_name(const char* s); const char* get_name() { - return filename_.string(); + return filename_.c_str(); } const char* dir(); void close(); @@ -48,8 +47,8 @@ class OcFile { #if HAVE_IV int chooser_type_; #endif - CopyString filename_; - CopyString dirname_; + std::string filename_; + std::string dirname_; FILE* file_; #ifdef WIN32 bool binary_; diff --git a/src/ivoc/oclist.cpp b/src/ivoc/oclist.cpp index ea736c7726..0d80eee882 100644 --- a/src/ivoc/oclist.cpp +++ b/src/ivoc/oclist.cpp @@ -1,7 +1,6 @@ #include <../../nrnconf.h> #include -#include #include "classreg.h" #include "oclist.h" #include "oc2iv.h" diff --git a/src/ivoc/ocpointer.cpp b/src/ivoc/ocpointer.cpp index b1edf7be92..a1cc1b04f9 100644 --- a/src/ivoc/ocpointer.cpp +++ b/src/ivoc/ocpointer.cpp @@ -117,13 +117,12 @@ void OcPointer_reg() { sv->u.ctemplate->steer = steer_val; } -StmtInfo::StmtInfo(const char* s) { - stmt_ = new CopyString(s); +StmtInfo::StmtInfo(const char* s) + : stmt_(s) { parse(); } StmtInfo::~StmtInfo() { - delete stmt_; hoc_free_list(&symlist_); } @@ -134,7 +133,7 @@ void StmtInfo::parse() { symlist_ = NULL; ParseTopLevel ptl; bool see_arg = false; - for (s = stmt_->string(), d = buf; *s; ++s, ++d) { + for (s = stmt_.c_str(), d = buf; *s; ++s, ++d) { if (*s == '$' && s[1] == '1') { strcpy(d, "hoc_ac_"); s++; diff --git a/src/ivoc/ocpointer.h b/src/ivoc/ocpointer.h index 09529bc325..9a7dabf905 100644 --- a/src/ivoc/ocpointer.h +++ b/src/ivoc/ocpointer.h @@ -2,7 +2,6 @@ #define ocpointer_h #include -#include #include "oc2iv.h" class StmtInfo; @@ -24,7 +23,7 @@ class StmtInfo { virtual ~StmtInfo(); void play_one(double); void parse(); - CopyString* stmt_; + std::string stmt_{}; Symlist* symlist_; Symbol* symstmt_; }; diff --git a/src/ivoc/strfun.cpp b/src/ivoc/strfun.cpp index f9c1618d93..095f3f049b 100644 --- a/src/ivoc/strfun.cpp +++ b/src/ivoc/strfun.cpp @@ -1,5 +1,4 @@ #include <../../nrnconf.h> -#include #include #include #include @@ -21,10 +20,6 @@ extern int nrn_is_artificial(int); extern int hoc_return_type_code; -inline unsigned long key_to_hash(String& s) { - return s.hash(); -} - static double l_substr(void*) { char* s1 = gargstr(1); char* s2 = gargstr(2); @@ -43,18 +38,14 @@ static double l_len(void*) { } static double l_head(void*) { - String text(gargstr(1)); + std::string text(gargstr(1)); Regexp r(gargstr(2)); - r.Search(text.string(), text.length(), 0, text.length()); + r.Search(text.c_str(), text.size(), 0, text.size()); int i = r.BeginningOfMatch(); // text.set_to_left(i); doesnt work char** head = hoc_pgargstr(3); if (i > 0) { - char* buf = new char[i + 1]; - strncpy(buf, text.string(), i); - buf[i] = '\0'; - hoc_assign_str(head, buf); - delete[] buf; + hoc_assign_str(head, text.substr(0, i).c_str()); } else { hoc_assign_str(head, ""); } @@ -63,13 +54,13 @@ static double l_head(void*) { } static double l_tail(void*) { - CopyString text(gargstr(1)); + std::string text(gargstr(1)); Regexp r(gargstr(2)); - r.Search(text.string(), text.length(), 0, text.length()); + r.Search(text.c_str(), text.size(), 0, text.size()); int i = r.EndOfMatch(); char** tail = hoc_pgargstr(3); if (i >= 0) { - hoc_assign_str(tail, text.string() + i); + hoc_assign_str(tail, text.c_str() + i); } else { hoc_assign_str(tail, ""); } @@ -78,16 +69,16 @@ static double l_tail(void*) { } static double l_left(void*) { - CopyString text(gargstr(1)); - CopyString newtext = text.left(int(chkarg(2, 0, strlen(gargstr(1))))); - hoc_assign_str(hoc_pgargstr(1), newtext.string()); + std::string text(gargstr(1)); + std::string newtext = text.substr(0, int(chkarg(2, 0, strlen(gargstr(1))))); + hoc_assign_str(hoc_pgargstr(1), newtext.c_str()); return 1.; } static double l_right(void*) { - CopyString text(gargstr(1)); - CopyString newtext = text.right(int(chkarg(2, 0, strlen(gargstr(1))))); - hoc_assign_str(hoc_pgargstr(1), newtext.string()); + std::string text(gargstr(1)); + std::string newtext = text.substr(int(chkarg(2, 0, strlen(gargstr(1))))); + hoc_assign_str(hoc_pgargstr(1), newtext.c_str()); return 1.; } @@ -358,8 +349,7 @@ IvocAliases::~IvocAliases() { } } Symbol* IvocAliases::lookup(const char* name) { - String s(name); - const auto& it = symtab_.find(s); + const auto& it = symtab_.find(name); if (it != symtab_.end()) { return it->second; } @@ -374,14 +364,12 @@ Symbol* IvocAliases::install(const char* name) { sp->cpublic = 0; // cannot be 2 or cannot be freed sp->extra = 0; sp->arayinfo = 0; - String s(sp->name); - symtab_.emplace(s, sp); + symtab_.try_emplace(sp->name, sp); return sp; } void IvocAliases::remove(Symbol* sym) { hoc_free_symspace(sym); - String s(sym->name); - auto it = symtab_.find(s); + auto it = symtab_.find(sym->name); symtab_.erase(it); free(sym->name); free(sym); diff --git a/src/ivoc/symchoos.cpp b/src/ivoc/symchoos.cpp index ab5de02edb..ea9048bf58 100644 --- a/src/ivoc/symchoos.cpp +++ b/src/ivoc/symchoos.cpp @@ -81,7 +81,7 @@ class SymChooserImpl { int* filter_map_; SymDirectory** dir_; SymChooserAction* action_; - const String* selected_; + std::string selected_; CopyString last_selected_; int last_index_; Style* style_; @@ -200,7 +200,7 @@ static double text(void* v) { #if HAVE_IV IFGUI SymChooser* sc = (SymChooser*) v; - hoc_assign_str(hoc_pgargstr(1), sc->selected()->string()); + hoc_assign_str(hoc_pgargstr(1), sc->selected().c_str()); ENDGUI return 0.; #else @@ -247,7 +247,7 @@ SymChooser::~SymChooser() { delete impl_; } -const String* SymChooser::selected() const { +const std::string& SymChooser::selected() const { return impl_->selected_; } @@ -506,7 +506,7 @@ void SymChooserImpl::load(int bindex) { filter_map_ = index; // printf("loading %d\n", bindex); for (int i = 0; i < dircount; i++) { - const String& f = d.name(i); + const String& f = d.name(i).c_str(); bool is_dir = d.is_directory(i); if ((is_dir && filtered(f, directory_filter_)) || (!is_dir && filtered(f, filter_))) { Glyph* name = kit.label(f); @@ -529,7 +529,7 @@ void SymChooserImpl::load(int bindex) { // to avoid a premature browser request which ends up showing an // empty list. fbrowser_[bindex]->refresh(); - editor_->field(d.path()); + editor_->field(d.path().c_str()); kit.pop_style(); } @@ -563,7 +563,7 @@ bool SymChooserImpl::filtered(const String& name, FieldEditor* e) { if (s == NULL || s->length() == 0) { return true; } - return s == NULL || s->length() == 0 || SymDirectory::match(name, *s); + return s == NULL || s->length() == 0 || SymDirectory::match(name.string(), s->string()); } void SymChooserImpl::accept_browser_index(int bindex) { @@ -573,8 +573,8 @@ void SymChooserImpl::accept_browser_index(int bindex) { } // i = filter_map_[i]; SymDirectory* dir = dir_[bindex]; - const String& path = dir->path(); - const String& name = dir->name(i); + const String& path = dir->path().c_str(); + const String& name = dir->name(i).c_str(); Symbol* sym = dir->symbol(i); int length = path.length() + name.length(); auto const tmp_len = length + 2; @@ -584,7 +584,7 @@ void SymChooserImpl::accept_browser_index(int bindex) { editor_->field(tmp); last_selected_ = tmp; last_index_ = i; - selected_ = editor_->text(); + selected_ = editor_->text()->string(); if (dir->is_directory(i)) { if (chdir(bindex, i)) { fchooser_->focus(editor_); @@ -600,7 +600,7 @@ void SymChooserImpl::accept_browser_index(int bindex) { } double* SymChooserImpl::selected_var() { - if (last_index_ != -1 && strcmp(selected_->string(), last_selected_.string()) == 0) { + if (last_index_ != -1 && selected_ == last_selected_.string()) { SymDirectory* dir = dir_[browser_index_]; return dir->variable(last_index_); } else { @@ -609,7 +609,7 @@ double* SymChooserImpl::selected_var() { } int SymChooserImpl::selected_vector_count() { - if (last_index_ != -1 && strcmp(selected_->string(), last_selected_.string()) == 0) { + if (last_index_ != -1 && selected_ == last_selected_.string()) { SymDirectory* dir = dir_[browser_index_]; return dir->whole_vector(last_index_); } else { @@ -625,15 +625,15 @@ void SymChooserImpl::accept_browser() { return; } // i = filter_map_[i]; - const String& path = dir_[bi]->path(); - const String& name = dir_[bi]->name(i); + const String& path = dir_[bi]->path().c_str(); + const String& name = dir_[bi]->name(i).c_str(); int length = path.length() + name.length(); char* tmp = new char[length + 1]; std::snprintf( tmp, length + 1, "%.*s%.*s", path.length(), path.string(), name.length(), name.string()); // printf("accept_browser %s\n", tmp); editor_->field(tmp); - selected_ = editor_->text(); + selected_ = editor_->text()->string(); if (dir_[bi]->is_directory(i)) { if (chdir(bi, i)) { fchooser_->focus(editor_); @@ -647,21 +647,19 @@ void SymChooserImpl::accept_browser() { } void SymChooserImpl::cancel_browser() { - selected_ = NULL; + selected_.clear(); fchooser_->dismiss(false); } void SymChooserImpl::editor_accept(FieldEditor* e) { - int i; - int bi = browser_index_; - if ((i = dir_[bi]->index(*e->text())) >= 0) { - if (!chdir(bi, i)) { - selected_ = &dir_[bi]->name(i); + if (int i = dir_[browser_index_]->index(e->text()->string()); i >= 0) { + if (!chdir(browser_index_, i)) { + selected_ = dir_[browser_index_]->name(i); fchooser_->dismiss(true); } return; } else { - selected_ = e->text(); + selected_ = e->text()->string(); fchooser_->dismiss(true); } } diff --git a/src/ivoc/symchoos.h b/src/ivoc/symchoos.h index 2d94449d09..dc465fe355 100644 --- a/src/ivoc/symchoos.h +++ b/src/ivoc/symchoos.h @@ -55,7 +55,7 @@ class SymChooser: public Dialog { SymChooser(SymDirectory*, WidgetKit*, Style*, SymChooserAction* = NULL, int nbrowser = 3); virtual ~SymChooser(); - virtual const String* selected() const; + virtual const std::string& selected() const; virtual double* selected_var(); virtual int selected_vector_count(); virtual void reread(); diff --git a/src/ivoc/symdir.cpp b/src/ivoc/symdir.cpp index 2a06893c21..9cc3d82535 100644 --- a/src/ivoc/symdir.cpp +++ b/src/ivoc/symdir.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "ocobserv.h" #include "utils/enumerate.h" @@ -44,7 +43,7 @@ class SymDirectoryImpl: public Observer { cTemplate* t_; std::vector symbol_lists_; - CopyString path_; + std::string path_; void load(int type); void load(int type, Symlist*); @@ -62,7 +61,7 @@ class SymDirectoryImpl: public Observer { }; static int compare_entries(const SymbolItem* e1, const SymbolItem* e2) { - int i = strcmp(e1->name().string(), e2->name().string()); + int i = strcmp(e1->name().c_str(), e2->name().c_str()); if (i == 0) { return e1->array_index() > e2->array_index(); } @@ -74,7 +73,7 @@ void SymDirectoryImpl::sort() { } // SymDirectory -SymDirectory::SymDirectory(const String& parent_path, +SymDirectory::SymDirectory(const std::string& parent_path, Object* parent_obj, Symbol* sym, int array_index, @@ -94,7 +93,7 @@ SymDirectory::SymDirectory(const String& parent_path, if (sym->type == TEMPLATE) { suffix = '_'; } - impl_->make_pathname(parent_path.string(), + impl_->make_pathname(parent_path.c_str(), sym->name, hoc_araystr(sym, array_index, obd), suffix); @@ -126,7 +125,7 @@ SymDirectory::SymDirectory(const String& parent_path, } break; default: - hoc_execerror("Don't know how to make a directory out of", path().string()); + hoc_execerror("Don't know how to make a directory out of", path().c_str()); break; } impl_->sort(); @@ -157,8 +156,8 @@ SymDirectory* SymDirectory::newsymdir(int index) { section_ref(d->impl_->sec_); d->impl_->load_section(); } - d->impl_->path_ = concat(path().string(), si->name().string()); - d->impl_->path_ = concat(d->impl_->path_.string(), "."); + 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; } @@ -258,7 +257,7 @@ double* SymDirectory::variable(int index) { } else { char buf[256], *cp; - Sprintf(buf, "%s%s", path().string(), name(index).string()); + 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]"); @@ -278,20 +277,20 @@ int SymDirectory::whole_vector(int index) { return impl_->symbol_lists_.at(index)->whole_vector(); } -const String& SymDirectory::path() const { +const std::string& SymDirectory::path() const { return impl_->path_; } int SymDirectory::count() const { return impl_->symbol_lists_.size(); } -const String& SymDirectory::name(int index) const { +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 String& name) const { +int SymDirectory::index(const std::string& name) const { for (const auto&& [i, symbol]: enumerate(impl_->symbol_lists_)) { if (name == symbol->name()) { return i; @@ -299,15 +298,15 @@ int SymDirectory::index(const String& name) const { } return -1; } -void SymDirectory::whole_name(int index, CopyString& s) const { - const String& s1 = impl_->path_; - const String& s2 = name(index); - s = concat(s1.string(), s2.string()); +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 String&, const String&) { +bool SymDirectory::match(const std::string&, const std::string&) { return true; } Symbol* SymDirectory::symbol(int index) const { diff --git a/src/ivoc/symdir.h b/src/ivoc/symdir.h index 20b269b4fc..02b1c1e44a 100644 --- a/src/ivoc/symdir.h +++ b/src/ivoc/symdir.h @@ -3,7 +3,6 @@ #include #include -#include struct Object; class SymDirectoryImpl; @@ -20,14 +19,14 @@ class IvocAliases { Symbol* symbol(int); Object* ob_; // not referenced - std::map symtab_; + std::map symtab_; }; /* List of Symbols considered as a directory */ class SymDirectory: public Resource { public: - SymDirectory(const String& parent_path, + SymDirectory(const std::string& parent_path, Object* parent_object, Symbol*, int array_index = 0, @@ -37,16 +36,16 @@ class SymDirectory: public Resource { SymDirectory(); virtual ~SymDirectory(); - virtual const String& path() const; + virtual const std::string& path() const; virtual int count() const; - virtual const String& name(int index) const; - virtual int index(const String&) const; - virtual void whole_name(int index, CopyString&) const; + virtual const std::string& name(int index) const; + virtual int index(const std::string&) const; + virtual void whole_name(int index, std::string&) const; virtual bool is_directory(int index) const; virtual double* variable(int index); virtual int whole_vector(int index); - static bool match(const String& name, const String& pattern); + static bool match(const std::string& name, const std::string& pattern); Symbol* symbol(int index) const; int array_index(int index) const; Object* object() const; // the parent_object diff --git a/src/ivoc/xmenu.cpp b/src/ivoc/xmenu.cpp index 082db077ec..82d50997f9 100644 --- a/src/ivoc/xmenu.cpp +++ b/src/ivoc/xmenu.cpp @@ -1456,7 +1456,6 @@ HocVarLabel::HocVarLabel(char** cpp, PolyGlyph* pg, Object* pyvar) } else { cp_ = *cpp_; } - variable_ = NULL; p_ = new Patch(LayoutKit::instance()->margin(WidgetKit::instance()->label(cp_), 3)); p_->ref(); pg->append(p_); @@ -1464,9 +1463,6 @@ HocVarLabel::HocVarLabel(char** cpp, PolyGlyph* pg, Object* pyvar) HocVarLabel::~HocVarLabel() { p_->unref(); - if (variable_) { - delete variable_; - } if (pyvar_) { hoc_obj_unref(pyvar_); if (cp_) { @@ -1476,9 +1472,9 @@ HocVarLabel::~HocVarLabel() { } void HocVarLabel::write(std::ostream& o) { - if (variable_ && cpp_) { + if (!variable_.empty() && cpp_) { char buf[256]; - Sprintf(buf, "xvarlabel(%s)", variable_->string()); + Sprintf(buf, "xvarlabel(%s)", variable_.c_str()); o << buf << std::endl; } else { o << "xlabel(\"\")" << std::endl; @@ -1879,12 +1875,11 @@ HocValEditor::HocValEditor(const char* name, canrun_ = canrun; active_ = false; domain_limits_ = NULL; - variable_ = NULL; pyvar_ = pyvar; if (pyvar) { hoc_obj_ref(pyvar); } else if (variable) { - variable_ = new CopyString(variable); + variable_ = variable; Symbol* sym = hoc_get_symbol(variable); if (sym && sym->extra) { domain_limits_ = sym->extra->parmlimits; @@ -1896,9 +1891,6 @@ HocValEditor::HocValEditor(const char* name, HocValEditor::~HocValEditor() { // printf("~HocValEditor\n"); - if (variable_) { - delete variable_; - } if (pyvar_) { hoc_obj_unref(pyvar_); } @@ -1942,8 +1934,8 @@ void HocValEditor::set_val(double x) { Oc oc; if (pval_) { *pval_ = hoc_ac_; - } else if (variable_) { - Sprintf(buf, "%s = hoc_ac_\n", variable_->string()); + } else if (!variable_.empty()) { + Sprintf(buf, "%s = hoc_ac_\n", variable_.c_str()); oc.run(buf); } } @@ -1954,9 +1946,9 @@ double HocValEditor::get_val() { return neuron::python::methods.guigetval(pyvar_); } else if (pval_) { return *pval_; - } else if (variable_) { + } else if (!variable_.empty()) { Oc oc; - Sprintf(buf, "hoc_ac_ = %s\n", variable_->string()); + Sprintf(buf, "hoc_ac_ = %s\n", variable_.c_str()); oc.run(buf); return hoc_ac_; } else { @@ -1983,8 +1975,8 @@ void HocValEditor::audit() { auto sout = std::stringstream{}; if (pyvar_) { return; - } else if (variable_) { - sout << variable_->string() << " = " << fe_->text()->string(); + } else if (!variable_.empty()) { + sout << variable_ << " = " << fe_->text()->string(); } else if (pval_) { sout << "// " << pval_ << " set to " << fe_->text()->string(); } @@ -2002,9 +1994,9 @@ void HocValEditor::updateField() { } else if (pval_) { Sprintf(buf, xvalue_format->string(), *pval_); hoc_ac_ = *pval_; - } else if (variable_) { + } else if (!variable_.empty()) { Oc oc; - Sprintf(buf, "hoc_ac_ = %s\n", variable_->string()); + Sprintf(buf, "hoc_ac_ = %s\n", variable_.c_str()); if (oc.run(buf, 0)) { strcpy(buf, "Doesn't exist"); } else { @@ -2021,10 +2013,10 @@ void HocValEditor::updateField() { void HocValEditor::write(std::ostream& o) { char buf[200]; Oc oc; - if (variable_) { - Sprintf(buf, "hoc_ac_ = %s\n", variable_->string()); + if (!variable_.empty()) { + Sprintf(buf, "hoc_ac_ = %s\n", variable_.c_str()); oc.run(buf); - Sprintf(buf, "%s = %g", variable_->string(), hoc_ac_); + Sprintf(buf, "%s = %g", variable_.c_str(), hoc_ac_); } else if (pval_) { Sprintf(buf, "/* don't know the hoc path to %g", *pval_); return; @@ -2044,7 +2036,7 @@ void HocValEditor::write(std::ostream& o) { 200, "xvalue(\"%s\",\"%s\", %d,\"%s\", %d, %d )", getStr(), - variable_->string(), + variable_.c_str(), hoc_default_val_editor(), hideQuote(action_->name()), (int) canrun_, @@ -2053,8 +2045,8 @@ void HocValEditor::write(std::ostream& o) { } const char* HocValEditor::variable() const { - if (variable_) { - return variable_->string(); + if (!variable_.empty()) { + return variable_.c_str(); } else { return NULL; } @@ -2321,28 +2313,22 @@ void HocPanel::data_path(HocDataPaths* hdp, bool append) { } void HocValEditor::data_path(HocDataPaths* hdp, bool append) { - if (!variable_) { + if (variable_.empty()) { auto* const pval_raw = static_cast(pval_); if (append) { hdp->append(pval_raw); } else { - String* s = hdp->retrieve(pval_raw); - if (s) { - variable_ = new CopyString(s->string()); - } + variable_ = hdp->retrieve(pval_raw); } } } void HocVarLabel::data_path(HocDataPaths* hdp, bool append) { - if (cpp_ && !variable_) { + if (cpp_ && variable_.empty()) { if (append) { hdp->append(cpp_); } else { - String* s = hdp->retrieve(cpp_); - if (s) { - variable_ = new CopyString(s->string()); - } + variable_ = hdp->retrieve(cpp_); } } } @@ -2638,7 +2624,6 @@ OcSlider::OcSlider(neuron::container::data_handle pd, Object* pysend) : HocUpdateItem("") { resolution_ = resolution; - variable_ = NULL; pval_ = pd; pyvar_ = pyvar; if (pyvar_) { @@ -2663,9 +2648,6 @@ OcSlider::~OcSlider() { delete send_; } delete bv_; - if (variable_) { - delete variable_; - } if (pyvar_) { hoc_obj_unref(pyvar_); } @@ -2704,8 +2686,8 @@ void OcSlider::audit() { auto sout = std::stringstream{}; char buf[200]; Sprintf(buf, "%g", *pval_); - if (variable_) { - sout << variable_->string() << " = " << buf << "\n"; + if (!variable_.empty()) { + sout << variable_.c_str() << " = " << buf << "\n"; } else if (pval_) { sout << "// " << pval_ << " set to " << buf << "\n"; } @@ -2760,25 +2742,22 @@ void OcSlider::check_pointer(void* v, int size) { } } void OcSlider::data_path(HocDataPaths* hdp, bool append) { - if (!variable_ && pval_) { + if (variable_.empty() && pval_) { auto* const pval_raw = static_cast(pval_); if (append) { hdp->append(pval_raw); } else { - String* s = hdp->retrieve(pval_raw); - if (s) { - variable_ = new CopyString(s->string()); - } + variable_ = hdp->retrieve(pval_raw); } } } void OcSlider::write(std::ostream& o) { - if (variable_) { + if (!variable_.empty()) { char buf[256]; if (send_) { Sprintf(buf, "xslider(&%s, %g, %g, \"%s\", %d, %d)", - variable_->string(), + variable_.c_str(), bv_->lower(Dimension_X), bv_->upper(Dimension_X), hideQuote(send_->name()), @@ -2787,7 +2766,7 @@ void OcSlider::write(std::ostream& o) { } else { Sprintf(buf, "xslider(&%s, %g, %g, %d, %d)", - variable_->string(), + variable_.c_str(), bv_->lower(Dimension_X), bv_->upper(Dimension_X), vert_, @@ -2837,7 +2816,6 @@ HocStateButton::HocStateButton(neuron::container::data_handle pd, if (pyvar_) { hoc_obj_ref(pyvar_); } - variable_ = NULL; name_ = new CopyString(text); action_ = action; action->hoc_item(this); @@ -2850,8 +2828,6 @@ HocStateButton::HocStateButton(neuron::container::data_handle pd, HocStateButton::~HocStateButton() { - if (variable_) - delete variable_; if (pyvar_) { hoc_obj_unref(pyvar_); } @@ -2934,32 +2910,29 @@ void HocStateButton::check_pointer(void* v, int size) { } void HocStateButton::data_path(HocDataPaths* hdp, bool append) { - if (!variable_ && pval_) { + if (variable_.empty() && pval_) { auto* const pval_raw = static_cast(pval_); if (append) { hdp->append(pval_raw); } else { - String* s = hdp->retrieve(pval_raw); - if (s) { - variable_ = new CopyString(s->string()); - } + variable_ = hdp->retrieve(pval_raw); } } } void HocStateButton::write(std::ostream& o) { - if (variable_) { + if (!variable_.empty()) { char buf[256]; if (style_ == PALETTE) { Sprintf(buf, "xstatebutton(\"%s\",&%s,\"%s\")", name_->string(), - variable_->string(), + variable_.c_str(), hideQuote(action_->name())); } else { Sprintf(buf, "xcheckbox(\"%s\",&%s,\"%s\")", name_->string(), - variable_->string(), + variable_.c_str(), hideQuote(action_->name())); } o << buf << std::endl; @@ -3000,7 +2973,6 @@ HocStateMenuItem::HocStateMenuItem(neuron::container::data_handle pd, if (pyvar_) { hoc_obj_ref(pyvar_); } - variable_ = NULL; name_ = new CopyString(text); action_ = action; action->hoc_item(this); @@ -3013,8 +2985,6 @@ HocStateMenuItem::HocStateMenuItem(neuron::container::data_handle pd, HocStateMenuItem::~HocStateMenuItem() { - if (variable_) - delete variable_; delete name_; if (pyvar_) { hoc_obj_unref(pyvar_); @@ -3098,26 +3068,23 @@ void HocStateMenuItem::check_pointer(void* v, int size) { } void HocStateMenuItem::data_path(HocDataPaths* hdp, bool append) { - if (!variable_ && pval_) { + if (variable_.empty() && pval_) { auto* const pval_raw = static_cast(pval_); if (append) { hdp->append(pval_raw); } else { - String* s = hdp->retrieve(pval_raw); - if (s) { - variable_ = new CopyString(s->string()); - } + variable_ = hdp->retrieve(pval_raw); } } } void HocStateMenuItem::write(std::ostream& o) { - if (variable_) { + if (!variable_.empty()) { char buf[256]; Sprintf(buf, "xcheckbox(\"%s\",&%s,\"%s\")", name_->string(), - variable_->string(), + variable_.c_str(), hideQuote(action_->name())); o << buf << std::endl; diff --git a/src/ivoc/xmenu.h b/src/ivoc/xmenu.h index 81eb9d1e85..929bb84511 100644 --- a/src/ivoc/xmenu.h +++ b/src/ivoc/xmenu.h @@ -207,7 +207,7 @@ class HocVarLabel: public HocUpdateItem { Patch* p_; char** cpp_; char* cp_; - CopyString* variable_; + std::string variable_{}; Object* pyvar_; }; @@ -332,7 +332,7 @@ class HocValEditor: public HocUpdateItem { bool active_; bool canrun_; HocAction* action_; - CopyString* variable_; + std::string variable_{}; neuron::container::data_handle pval_; ValEdLabel* prompt_; float* domain_limits_; @@ -445,7 +445,7 @@ class OcSlider: public HocUpdateItem, public Observer { HocCommand* send_; neuron::container::data_handle pval_; Object* pyvar_; - CopyString* variable_; + std::string variable_{}; bool scrolling_; bool vert_; bool slow_; @@ -475,7 +475,7 @@ class HocStateButton: public HocUpdateItem, public Observer { private: int style_; - CopyString* variable_; + std::string variable_{}; CopyString* name_; neuron::container::data_handle pval_; Object* pyvar_; @@ -504,7 +504,7 @@ class HocStateMenuItem: public HocUpdateItem, public Observer { virtual void print(Printer*, const Allocation&) const; private: - CopyString* variable_; + std::string variable_{}; CopyString* name_; neuron::container::data_handle pval_; Object* pyvar_; diff --git a/src/ivos/InterViews/enter-scope.h b/src/ivos/InterViews/enter-scope.h index ac33ced9e6..530363dd6c 100644 --- a/src/ivos/InterViews/enter-scope.h +++ b/src/ivos/InterViews/enter-scope.h @@ -38,14 +38,9 @@ #ifndef iv_os__scope_h -/* - * Use OS bool and String definitions. - */ - #include #include -#define String _lib_os(String) #define u_char _lib_os(u_char) #endif diff --git a/src/ivos/OS/_defines.h b/src/ivos/OS/_defines.h index e6098beebe..4bbe5cc7c5 100755 --- a/src/ivos/OS/_defines.h +++ b/src/ivos/OS/_defines.h @@ -1,6 +1,3 @@ #define u_char _lib_os(u_char) -#define CopyString _lib_os(CopyString) #define List _lib_os(List) -#define NullTerminatedString _lib_os(NullTerminatedString) #define PtrList _lib_os(PtrList) -#define String _lib_os(String) diff --git a/src/ivos/OS/_undefs.h b/src/ivos/OS/_undefs.h index 195b4e9ae6..8998a61956 100755 --- a/src/ivos/OS/_undefs.h +++ b/src/ivos/OS/_undefs.h @@ -1,6 +1,3 @@ #undef u_char -#undef CopyString #undef List -#undef NullTerminatedString #undef PtrList -#undef String diff --git a/src/ivos/OS/enter-scope.h b/src/ivos/OS/enter-scope.h index 7e96a28f03..856b669595 100755 --- a/src/ivos/OS/enter-scope.h +++ b/src/ivos/OS/enter-scope.h @@ -27,7 +27,6 @@ #include -#undef String #undef u_char #include diff --git a/src/ivos/OS/string.h b/src/ivos/OS/string.h deleted file mode 100644 index 97ec9a1b86..0000000000 --- a/src/ivos/OS/string.h +++ /dev/null @@ -1,154 +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. - */ - -#ifndef os_string_h -#define os_string_h - -/* - * String - simple (non-copying) string class - */ - -#include - -class String { -public: -#ifdef _DELTA_EXTENSIONS -#pragma __static_class -#endif - String(); - String(const char*); - String(const char*, int length); - String(const String&); - virtual ~String(); - - const char* string() const; - int length() const; - - virtual unsigned long hash() const; - virtual String& operator =(const String&); - virtual String& operator =(const char*); - virtual bool operator ==(const String&) const; - virtual bool operator ==(const char*) const; - virtual bool operator !=(const String&) const; - virtual bool operator !=(const char*) const; - virtual bool operator >(const String&) const; - virtual bool operator >(const char*) const; - virtual bool operator >=(const String&) const; - virtual bool operator >=(const char*) const; - virtual bool operator <(const String&) const; - virtual bool operator <(const char*) const; - virtual bool operator <=(const String&) const; - virtual bool operator <=(const char*) const; - - virtual bool case_insensitive_equal(const String&) const; - virtual bool case_insensitive_equal(const char*) const; - - u_char operator [](int index) const; - virtual String substr(int start, int length) const; - String left(int length) const; - String right(int start) const; - - virtual void set_to_substr(int start, int length); - void set_to_left(int length); - void set_to_right(int start); - - virtual int search(int start, u_char) const; - int index(u_char) const; - int rindex(u_char) const; - - virtual bool convert(int&) const; - virtual bool convert(long&) const; - virtual bool convert(float&) const; - virtual bool convert(double&) const; - - virtual bool null_terminated() const; -protected: - virtual void set_value(const char*); - virtual void set_value(const char*, int); -private: - const char* data_; - int length_; -}; - -class CopyString : public String { -public: -#ifdef _DELTA_EXTENSIONS -#pragma __static_class -#endif - CopyString(); - CopyString(const char*); - CopyString(const char*, int length); - CopyString(const String&); - CopyString(const CopyString&); - virtual ~CopyString(); - - virtual String& operator =(const CopyString&); - virtual String& operator =(const String&); - virtual String& operator =(const char*); - - virtual bool null_terminated() const; -protected: - virtual void set_value(const char*); - virtual void set_value(const char*, int); -private: - void strfree(); -}; - -class NullTerminatedString : public String { -public: -#ifdef _DELTA_EXTENSIONS -#pragma __static_class -#endif - NullTerminatedString(); - NullTerminatedString(const String&); - NullTerminatedString(const NullTerminatedString&); - virtual ~NullTerminatedString(); - - virtual String& operator =(const String&); - virtual String& operator =(const char*); - - virtual bool null_terminated() const; -private: - bool allocated_; - - void assign(const String&); - void strfree(); -}; - -inline const char* String::string() const { return data_; } -inline int String::length() const { return length_; } -inline u_char String::operator [](int index) const { - return ((u_char*)data_)[index]; -} - -inline String String::left(int length) const { return substr(0, length); } -inline String String::right(int start) const { return substr(start, -1); } - -inline void String::set_to_left(int length) { set_to_substr(0, length); } -inline void String::set_to_right(int start) { set_to_substr(start, -1); } - -inline int String::index(u_char c) const { return search(0, c); } -inline int String::rindex(u_char c) const { return search(-1, c); } - -#endif diff --git a/src/ivos/string.cpp b/src/ivos/string.cpp deleted file mode 100644 index 7be01128b2..0000000000 --- a/src/ivos/string.cpp +++ /dev/null @@ -1,403 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include <../../nrnconf.h> -#endif -/* - * Copyright (c) 1987, 1988, 1989, 1990, 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. - */ - -#include -#include -#include -#include - -/* - * Just to be sure ... - */ - -/* fails on mac osx -extern "C" { -#ifndef tolower - extern int tolower(int); -#endif -#ifndef toupper - extern int toupper(int); -#endif - extern long int strtol(const char*, char**, int); - extern double strtod(const char*, char**); -} -*/ - -String::String() { - data_ = nil; - length_ = 0; -} - -String::String(const char* s) { - data_ = s; - length_ = strlen(s); -} - -String::String(const char* s, int n) { - data_ = s; - length_ = n; -} - -String::String(const String& s) { - data_ = s.data_; - length_ = s.length_; -} - -String::~String() { } - -unsigned long String::hash() const { - const char* p; - unsigned long v = 0; - if (length_ == -1) { - for (p = data_; *p != '\0'; p++) { - v = (v << 1) ^ (*p); - } - String* s = (String*)this; - s->length_ = p - data_; - } else { - const char* q = &data_[length_]; - for (p = data_; p < q; p++) { - v = (v << 1) ^ (*p); - } - } - unsigned long t = v >> 10; - t ^= (t >> 10); - return v ^ t; -} - -String& String::operator =(const String& s) { - data_ = s.data_; - length_ = s.length_; - return *this; -} - -String& String::operator =(const char* s) { - data_ = s; - length_ = strlen(s); - return *this; -} - -bool String::operator ==(const String& s) const { - return (length_ == s.length_) && (strncmp(data_, s.data_, length_) == 0); -} - -bool String::operator ==(const char* s) const { - return (strncmp(data_, s, length_) == 0) && (s[length_] == '\0'); -} - -bool String::operator !=(const String& s) const { - return (length_ != s.length_) || (strncmp(data_, s.data_, length_) != 0); -} - -bool String::operator !=(const char* s) const { - return (strncmp(data_, s, length_) != 0) || (s[length_] != '\0'); -} - -bool String::operator >(const String& s) const { - return strncmp(data_, s.data_, length_) > 0; -} - -bool String::operator >(const char* s) const { - return strncmp(data_, s, length_) > 0; -} - -bool String::operator >=(const String& s) const { - return strncmp(data_, s.data_, length_) >= 0; -} - -bool String::operator >=(const char* s) const { - return strncmp(data_, s, length_) >= 0; -} - -bool String::operator <(const String& s) const { - return strncmp(data_, s.data_, length_) < 0; -} - -bool String::operator <(const char* s) const { - return strncmp(data_, s, length_) < 0; -} - -bool String::operator <=(const String& s) const { - return strncmp(data_, s.data_, length_) <= 0; -} - -bool String::operator <=(const char* s) const { - return strncmp(data_, s, length_) <= 0; -} - -bool String::case_insensitive_equal(const String& s) const { - if (length() != s.length()) { - return false; - } - const char* p = string(); - const char* p2 = s.string(); - const char* q = p + length(); - for (; p < q; p++, p2++) { - int c1 = *p; - int c2 = *p2; - if (c1 != c2 && tolower(c1) != tolower(c2)) { - return false; - } - } - return true; -} - -bool String::case_insensitive_equal(const char* s) const { - return case_insensitive_equal(String(s)); -} - -/* - * A negative value for start initializes the position at the end - * of the string before indexing. Any negative length makes - * the substring extend to the end of the string. - */ - -String String::substr(int start, int length) const { - if (start >= length_ || start < -length_) { - /* should raise exception */ - return String(""); - } - int pos = (start >= 0) ? start : (length_ + start); - if (pos + length > length_) { - /* should raise exception */ - return String(""); - } - int len = (length >= 0) ? length : (length_ - pos); - return String(data_ + pos, len); -} - -void String::set_to_substr(int start, int length) { - if (start > length_ || start < -length_) { - /* should raise exception */ - return; - } - int pos = (start >= 0) ? start : (length_ + start); - if (pos + length > length_) { - /* should raise exception */ - return; - } - int len = (length >= 0) ? length : (length_ - pos); - data_ += pos; - length_ = len; -} - -bool String::null_terminated() const { return false; } - -void String::set_value(const char* s) { - data_ = s; - length_ = strlen(s); -} - -void String::set_value(const char* s, int len) { - data_ = s; - length_ = len; -} - -/* - * A negative value for start initializes the position to the end - * of the string before indexing and searches right-to-left. - */ - -int String::search(int start, u_char c) const { - if (start >= length_ || start < -length_) { - /* should raise exception */ - return -1; - } - if (start >= 0) { - const char* end = data_ + length_; - for (const char* p = data_ + start; p < end; p++) { - if (*p == c) { - return p - data_; - } - } - } else { - for (const char* p = data_ + length_ + start; p >= data_; p--) { - if (*p == c) { - return p - data_; - } - } - } - return -1; -} - -/* - * Convert a string to binary value. - */ - -bool String::convert(int& value) const { - NullTerminatedString s(*this); - const char* str = s.string(); - char* ptr; - value = (int)strtol(str, &ptr, 0); - return ptr != str; -} - -bool String::convert(long& value) const { - NullTerminatedString s(*this); - const char* str = s.string(); - char* ptr; - value = strtol(str, &ptr, 0); - return ptr != str; -} - -bool String::convert(float& value) const { - NullTerminatedString s(*this); - const char* str = s.string(); - char* ptr; - value = (float)strtod(str, &ptr); - return ptr != str; -} - -bool String::convert(double& value) const { - NullTerminatedString s(*this); - const char* str = s.string(); - char* ptr; - value = strtod(str, &ptr); - return ptr != str; -} - -/* class CopyString */ - -CopyString::CopyString() : String() { } - -CopyString::CopyString(const char* s) : String() { - set_value(s); -} - -CopyString::CopyString(const char* s, int length) : String() { - set_value(s, length); -} - -CopyString::CopyString(const String& s) : String() { - set_value(s.string(), s.length()); -} - -CopyString::CopyString(const CopyString& s) : String() { - set_value(s.string(), s.length()); -} - -CopyString::~CopyString() { - strfree(); -} - -String& CopyString::operator =(const CopyString& s) { - strfree(); - set_value(s.string(), s.length()); - return *this; -} - -String& CopyString::operator =(const String& s) { - strfree(); - set_value(s.string(), s.length()); - return *this; -} - -String& CopyString::operator =(const char* s) { - strfree(); - set_value(s); - return *this; -} - -bool CopyString::null_terminated() const { return true; } - -void CopyString::set_value(const char* s) { - set_value(s, strlen(s)); -} - -/* - * Guarantee null-terminated string for compatibility with printf et al. - */ - -void CopyString::set_value(const char* s, int len) { - char* ns = new char[len + 1]; - ns[len] = '\0'; - String::set_value(strncpy(ns, s, len), len); -} - -void CopyString::strfree() { - char* s = (char*)(string()); - delete [] s; -} - -/* - * class NullTerminatedString - */ - -NullTerminatedString::NullTerminatedString() : String() { - allocated_ = false; -} - -NullTerminatedString::NullTerminatedString(const String& s) : String() { - assign(s); -} - -NullTerminatedString::NullTerminatedString( - const NullTerminatedString& s -) : String() { - allocated_ = false; - String::set_value(s.string(), s.length()); -} - -NullTerminatedString::~NullTerminatedString() { - strfree(); -} - -String& NullTerminatedString::operator =(const String& s) { - strfree(); - assign(s); - return *this; -} - -String& NullTerminatedString::operator =(const char* s) { - strfree(); - allocated_ = false; - String::set_value(s, strlen(s)); - return *this; -} - -bool NullTerminatedString::null_terminated() const { return true; } - -void NullTerminatedString::assign(const String& s) { - if (s.null_terminated()) { - allocated_ = false; - String::set_value(s.string(), s.length()); - } else { - allocated_ = true; - int len = s.length(); - char* ns = new char[len + 1]; - ns[len] = '\0'; - String::set_value(strncpy(ns, s.string(), len), len); - } -} - -void NullTerminatedString::strfree() { - if (allocated_) { - char* s = (char*)(string()); - delete [] s; - allocated_ = false; - } -} 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/neuron/container/memory_usage.hpp b/src/neuron/container/memory_usage.hpp index c9d833d6ff..33c3cfa5db 100644 --- a/src/neuron/container/memory_usage.hpp +++ b/src/neuron/container/memory_usage.hpp @@ -121,13 +121,11 @@ struct MemoryUsage { ModelMemoryUsage model{}; cache::ModelMemoryUsage cache_model{}; VectorMemoryUsage stable_pointers{}; - VectorMemoryUsage stable_identifiers{}; const MemoryUsage& operator+=(const MemoryUsage& other) { model += other.model; cache_model += other.cache_model; stable_pointers += other.stable_pointers; - stable_identifiers += other.stable_identifiers; return *this; } @@ -136,7 +134,6 @@ struct MemoryUsage { auto total = model.compute_total(); total += cache_model.compute_total(); total += stable_pointers; - total += stable_identifiers; return total; } @@ -174,7 +171,6 @@ struct MemoryUsageSummary { add(memory_usage.model); add(memory_usage.cache_model); add(leaked, memory_usage.stable_pointers); - add(leaked, memory_usage.stable_identifiers); } private: diff --git a/src/neuron/container/non_owning_soa_identifier.hpp b/src/neuron/container/non_owning_soa_identifier.hpp index fc3a5e9cd7..18722269b1 100644 --- a/src/neuron/container/non_owning_soa_identifier.hpp +++ b/src/neuron/container/non_owning_soa_identifier.hpp @@ -13,6 +13,7 @@ namespace neuron::container { struct field_index { int field{}, array_index{}; }; + inline constexpr std::size_t invalid_row = std::numeric_limits::max(); /** @@ -27,6 +28,19 @@ struct non_owning_identifier_without_container { */ non_owning_identifier_without_container() = default; + non_owning_identifier_without_container(const non_owning_identifier_without_container& other) = + default; + non_owning_identifier_without_container(non_owning_identifier_without_container&& other) = + default; + + non_owning_identifier_without_container& operator=( + const non_owning_identifier_without_container&) = default; + non_owning_identifier_without_container& operator=(non_owning_identifier_without_container&&) = + default; + + ~non_owning_identifier_without_container() = default; + + /** * @brief Does the identifier refer to a valid entry? * @@ -105,21 +119,24 @@ struct non_owning_identifier_without_container { template friend struct soa; friend struct std::hash; - non_owning_identifier_without_container(std::size_t* ptr) - : m_ptr{ptr} {} + explicit non_owning_identifier_without_container(std::shared_ptr ptr) + : m_ptr{std::move(ptr)} {} void set_current_row(std::size_t row) { assert(m_ptr); *m_ptr = row; } + explicit non_owning_identifier_without_container(size_t row) + : m_ptr(std::make_shared(row)) {} + private: - std::size_t* m_ptr{}; + std::shared_ptr m_ptr{}; }; } // namespace neuron::container template <> struct std::hash { std::size_t operator()( neuron::container::non_owning_identifier_without_container const& h) noexcept { - return reinterpret_cast(h.m_ptr); + return reinterpret_cast(h.m_ptr.get()); } }; diff --git a/src/neuron/container/soa_identifier.hpp b/src/neuron/container/soa_identifier.hpp index 357cc3f08c..0402e3a0aa 100644 --- a/src/neuron/container/soa_identifier.hpp +++ b/src/neuron/container/soa_identifier.hpp @@ -12,17 +12,6 @@ #include namespace neuron::container { -namespace detail { -/** - * @brief The vector in which dying owning_identifier std::size_t's live. - * - * This is defined in container.cpp to avoid multiple-definition issues. - */ -extern std::vector>* identifier_defer_delete_storage; -VectorMemoryUsage compute_identifier_defer_delete_storage_size(); - -} // namespace detail - /** * @brief A non-owning permutation-stable identifier for a entry in a container. * @tparam Storage The type of the referred-to container. This might be a type @@ -81,28 +70,47 @@ struct owning_identifier { * @brief Create a non-null owning identifier by creating a new entry. */ owning_identifier(Storage& storage) - : owning_identifier{} { - // The default constructor has finished, so *this is a valid object. - auto tmp = storage.acquire_owning_identifier(); - swap(*this, tmp); + : owning_identifier(storage.acquire_owning_identifier()) {} + + owning_identifier(const owning_identifier&) = delete; + owning_identifier(owning_identifier&& other) noexcept + : m_ptr(std::move(other.m_ptr)) + , m_data_ptr(other.m_data_ptr) { + other.m_data_ptr = nullptr; + } + + owning_identifier& operator=(const owning_identifier&) = delete; + owning_identifier& operator=(owning_identifier&& other) { + destroy(); + + m_ptr = std::move(other.m_ptr); + + m_data_ptr = other.m_data_ptr; + other.m_data_ptr = nullptr; + + return *this; + } + + ~owning_identifier() { + destroy(); } /** * @brief Return a reference to the container in which this entry lives. */ Storage& underlying_storage() { - return *m_ptr.get_deleter().m_data_ptr; + return *m_data_ptr; } /** * @brief Return a const reference to the container in which this entry lives. */ Storage const& underlying_storage() const { - return *m_ptr.get_deleter().m_data_ptr; + return *m_data_ptr; } [[nodiscard]] operator non_owning_identifier() const { - return {const_cast(&underlying_storage()), m_ptr.get()}; + return {m_data_ptr, m_ptr}; } [[nodiscard]] operator non_owning_identifier_without_container() const { @@ -117,11 +125,7 @@ struct owning_identifier { */ [[nodiscard]] std::size_t current_row() const { assert(m_ptr); - return *m_ptr; - } - - friend void swap(owning_identifier& first, owning_identifier& second) { - std::swap(first.m_ptr, second.m_ptr); + return m_ptr.current_row(); } friend std::ostream& operator<<(std::ostream& os, owning_identifier const& oi) { @@ -132,63 +136,62 @@ struct owning_identifier { private: owning_identifier() = default; - struct deleter { - deleter() = default; - deleter(Storage& data_container) - : m_data_ptr{&data_container} {} - void operator()(std::size_t* p) const { - assert(m_data_ptr); - auto& data_container = *m_data_ptr; - assert(p); - // We should still be a valid reference at this point. - assert(*p < data_container.size()); - // Prove that the bookkeeping works. - assert(data_container.at(*p) == p); - bool terminate{false}; - // Delete the corresponding row from `data_container` - try { - data_container.erase(*p); - } catch (std::exception const& e) { - // Cannot throw from unique_ptr release/reset/destructor, this - // is the best we can do. Most likely what has happened is - // something like: - // auto const read_only_token = node_data.issue_frozen_token(); - // list_of_nodes.pop_back(); - // which tries to delete a row from a container in read-only mode. - std::cerr << "neuron::container::owning_identifier<" - << cxx_demangle(typeid(Storage).name()) - << "> destructor could not delete from the underlying storage: " - << e.what() << " [" << cxx_demangle(typeid(e).name()) - << "]. This is not recoverable, aborting." << std::endl; - terminate = true; - } - if (terminate) { - std::terminate(); - } - // We don't know how many people know the pointer `p`, so write a sentinel - // value to it and transfer ownership "elsewhere". - *p = invalid_row; - // This is to provide compatibility with NEURON's old nrn_notify_when_double_freed and - // nrn_notify_when_void_freed methods. - detail::notify_handle_dying(p); - // This is sort-of formalising a memory leak. In principle we could cleanup - // identifier_defer_delete_storage by scanning all our data structures and finding - // references to the pointers that it contains. In practice it seems unlikely that - // either this, or using std::shared_ptr just to avoid it, would be worth it. - if (detail::identifier_defer_delete_storage) { - detail::identifier_defer_delete_storage->emplace_back(p); - } else { - delete p; - } + + void destroy() { + if (!m_ptr) { + // Nothing to be done. + return; + } + + assert(m_data_ptr); + auto& data_container = *m_data_ptr; + + // We should still be a valid reference at this point. + assert(m_ptr); + assert(m_ptr.current_row() < data_container.size()); + + // Prove that the bookkeeping works. + assert(data_container.at(m_ptr.current_row()) == m_ptr); + + bool terminate = false; + // Delete the corresponding row from `data_container` + try { + data_container.erase(m_ptr.current_row()); + } catch (std::exception const& e) { + // Cannot throw from unique_ptr release/reset/destructor, this + // is the best we can do. Most likely what has happened is + // something like: + // auto const read_only_token = node_data.issue_frozen_token(); + // list_of_nodes.pop_back(); + // which tries to delete a row from a container in read-only mode. + std::cerr << "neuron::container::owning_identifier<" + << cxx_demangle(typeid(Storage).name()) + << "> destructor could not delete from the underlying storage: " << e.what() + << " [" << cxx_demangle(typeid(e).name()) + << "]. This is not recoverable, aborting." << std::endl; + terminate = true; } - Storage* m_data_ptr{}; - }; - std::unique_ptr m_ptr; + if (terminate) { + std::terminate(); + } + // We don't know how many people know the pointer `p`, so write a sentinel + // value to it and transfer ownership "elsewhere". + m_ptr.set_current_row(invalid_row); + + // This is to provide compatibility with NEURON's old nrn_notify_when_double_freed and + // nrn_notify_when_void_freed methods. + detail::notify_handle_dying(m_ptr); + } + + + non_owning_identifier_without_container m_ptr{}; + Storage* m_data_ptr{}; + template friend struct soa; void set_current_row(std::size_t new_row) { assert(m_ptr); - *m_ptr = new_row; + m_ptr.set_current_row(new_row); } /** * @brief Create a non-null owning identifier that owns the given row. @@ -198,8 +201,7 @@ struct owning_identifier { * be used without great care. */ owning_identifier(Storage& storage, std::size_t row) - : m_ptr{new std::size_t, storage} { - *m_ptr = row; - } + : m_ptr(row) + , m_data_ptr(&storage) {} }; } // namespace neuron::container diff --git a/src/neuron/model_data.hpp b/src/neuron/model_data.hpp index e8eb336e2a..9d71d80074 100644 --- a/src/neuron/model_data.hpp +++ b/src/neuron/model_data.hpp @@ -120,8 +120,6 @@ struct Model { void shrink_to_fit() { m_node_data.shrink_to_fit(); apply_to_mechanisms([](auto& mech_data) { mech_data.shrink_to_fit(); }); - - m_identifier_ptrs_for_deferred_deletion.shrink_to_fit(); } private: @@ -157,11 +155,6 @@ struct Model { * @brief Backing storage for defer_delete helper. */ std::vector m_ptrs_for_deferred_deletion{}; - - /** - * @brief Backing storage for global identifier_defer_delete_storage. - */ - std::vector> m_identifier_ptrs_for_deferred_deletion{}; }; struct model_sorted_token { diff --git a/src/nmodl/io.cpp b/src/nmodl/io.cpp index 82c4031c4b..88110a1b36 100644 --- a/src/nmodl/io.cpp +++ b/src/nmodl/io.cpp @@ -445,49 +445,3 @@ static int file_stack_empty() { } return (filestack->next == filestack); } - -/* adapted from : gist@jonathonreinhart/mkdir_p.c */ -int mkdir_p(const char* path) { - const size_t len = strlen(path); - char mypath[PATH_MAX]; - char* p; - - errno = 0; - - /* copy string so its mutable */ - if (len > sizeof(mypath) - 1) { - fprintf(stderr, "Output directory path too long\n"); - return -1; - } - - strcpy(mypath, path); - - /* iterate the string */ - for (p = mypath + 1; *p; p++) { - if (*p == '/') { - /* temporarily truncate */ - *p = '\0'; - -#if defined(_WIN32) - if (_mkdir(mypath) != 0) { -#else - if (mkdir(mypath, S_IRWXU) != 0) { -#endif - if (errno != EEXIST) - return -1; - } - *p = '/'; - } - } - -#if defined(_WIN32) - if (_mkdir(mypath) != 0) { -#else - if (mkdir(mypath, S_IRWXU) != 0) { -#endif - if (errno != EEXIST) - return -1; - } - - return 0; -} diff --git a/src/nmodl/modl.cpp b/src/nmodl/modl.cpp index 7e3859bde5..9523c7a2a1 100644 --- a/src/nmodl/modl.cpp +++ b/src/nmodl/modl.cpp @@ -28,12 +28,16 @@ /* the first arg may also be a file.mod (containing the .mod suffix)*/ -#include +#include #include #include "modl.h" #include +#include +#include + +namespace fs = std::filesystem; FILE *fin, /* input file descriptor for filename.mod */ /* or file2 from the second argument */ @@ -55,7 +59,6 @@ int nmodl_text = 1; List* filetxtlist; extern int yyparse(); -extern int mkdir_p(const char*); extern int vectorize; extern int numlist; @@ -67,58 +70,22 @@ static const char* pgm_name = "nmodl"; extern const char* RCS_version; extern const char* RCS_date; -static struct option long_options[] = {{"version", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"outdir", required_argument, 0, 'o'}, - {0, 0, 0, 0}}; - -static void show_options(char** argv) { - fprintf(stderr, "Source to source compiler from NMODL to C++\n"); - fprintf(stderr, "Usage: %s [options] Inputfile\n", argv[0]); - fprintf(stderr, "Options:\n"); - fprintf(stderr, - "\t-o | --outdir directory where output files will be written\n"); - fprintf(stderr, "\t-h | --help print this message\n"); - fprintf(stderr, "\t-v | --version print version number\n"); -} - -static void openfiles(char* given_filename, char* output_dir); +static void openfiles(const char* given_filename, const char* output_dir); int main(int argc, char** argv) { - int option = -1; - int option_index = 0; - char* output_dir = NULL; - - if (argc < 2) { - show_options(argv); - exit(1); - } + std::string output_dir{}; + std::string inputfile{}; - while ((option = getopt_long(argc, argv, ":vho:", long_options, &option_index)) != -1) { - switch (option) { - case 'v': - printf("%s\n", nmodl_version_); - exit(0); + CLI::App app{"Source to source compiler from NMODL to C++"}; + app.add_option("-o,--outdir", output_dir, "directory where output files will be written"); + app.set_version_flag("-v,--version", nmodl_version_, "print version number"); + app.set_help_flag("-h,--help", "print this message"); + app.add_option("Inputfile", inputfile)->required(); + app.allow_extras(); - case 'o': - output_dir = strdup(optarg); - break; + CLI11_PARSE(app, argc, argv); - case 'h': - show_options(argv); - exit(0); - - case ':': - fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt); - exit(-1); - - case '?': - default: - fprintf(stderr, "%s: invalid option `-%c' \n", argv[0], optopt); - exit(-1); - } - } - if ((argc - optind) > 1) { + if (!app.remaining().empty()) { fprintf(stderr, "%s: Warning several input files specified on command line but only one will be " "processed\n", @@ -130,9 +97,9 @@ int main(int argc, char** argv) { init(); /* keywords into symbol table, initialize * lists, etc. */ - std::strncpy(finname, argv[optind], sizeof(finname)); - - openfiles(finname, output_dir); /* .mrg else .mod, .var, .c */ + std::strcpy(finname, inputfile.c_str()); + openfiles(inputfile.c_str(), + output_dir.empty() ? nullptr : output_dir.c_str()); /* .mrg else .mod, .var, .c */ IGNORE(yyparse()); /* * At this point all blocks are fully processed except the kinetic @@ -247,7 +214,7 @@ int main(int argc, char** argv) { return 0; } -static void openfiles(char* given_filename, char* output_dir) { +static void openfiles(const char* given_filename, const char* output_dir) { char s[NRN_BUFSIZE]; char output_filename[NRN_BUFSIZE]; @@ -276,7 +243,9 @@ static void openfiles(char* given_filename, char* output_dir) { } } if (output_dir) { - if (mkdir_p(output_dir) != 0) { + try { + fs::create_directories(output_dir); + } catch (...) { fprintf(stderr, "Can't create output directory %s\n", output_dir); exit(1); } 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/nocpout.cpp b/src/nmodl/nocpout.cpp index 07722d0749..5c6535c300 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -389,7 +389,6 @@ extern void _nrn_cacheloop_reg(int, int);\n\ extern void hoc_register_limits(int, HocParmLimits*);\n\ extern void hoc_register_units(int, HocParmUnits*);\n\ extern void nrn_promote(Prop*, int, int);\n\ -extern Memb_func* memb_func;\n\ "); if (nmodl_text) { 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/nrncvode/cvtrset.cpp b/src/nrncvode/cvtrset.cpp index 8a72fc9522..f7edae1ce6 100644 --- a/src/nrncvode/cvtrset.cpp +++ b/src/nrncvode/cvtrset.cpp @@ -61,8 +61,8 @@ void Cvode::rhs_memb(neuron::model_sorted_token const& sorted_token, NrnThread* _nt) { errno = 0; for (CvMembList* cml = cmlist; cml; cml = cml->next) { - Memb_func* mf = memb_func + cml->index; - if (auto const current = mf->current; current) { + const Memb_func& mf = memb_func[cml->index]; + if (auto const current = mf.current; current) { for (auto& ml: cml->ml) { current(sorted_token, _nt, &ml, cml->index); if (errno && nrn_errno_check(cml->index)) { @@ -109,8 +109,8 @@ void Cvode::lhs_memb(neuron::model_sorted_token const& sorted_token, NrnThread* _nt) { CvMembList* cml; for (cml = cmlist; cml; cml = cml->next) { - Memb_func* mf = memb_func + cml->index; - if (auto const jacob = mf->jacob; jacob) { + const Memb_func& mf = memb_func[cml->index]; + if (auto const jacob = mf.jacob; jacob) { for (auto& ml: cml->ml) { jacob(sorted_token, _nt, &ml, cml->index); if (errno && nrn_errno_check(cml->index)) { diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index 2f9acf4fe3..d2dd5ffcb5 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -1600,10 +1600,10 @@ bool NetCvode::init_global() { CvMembList* last = 0; for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; - Memb_func* mf = memb_func + i; + const Memb_func& mf = memb_func[i]; Memb_list* ml = tml->ml; - if (ml->nodecount && (i == CAP || mf->current || mf->ode_count || mf->ode_matsol || - mf->ode_spec || mf->state)) { + if (ml->nodecount && (i == CAP || mf.current || mf.ode_count || mf.ode_matsol || + mf.ode_spec || mf.state)) { // maintain same order (not reversed) for // singly linked list built below cml = new CvMembList{i}; @@ -1625,7 +1625,7 @@ bool NetCvode::init_global() { cml->ml[0].nodeindices = ml->nodeindices; assert(ml->prop); cml->ml[0].prop = ml->prop; // used for ode_map even when hoc_mech = false - if (!mf->hoc_mech) { + if (!mf.hoc_mech) { cml->ml[0].pdata = ml->pdata; } cml->ml[0]._thread = ml->_thread; @@ -1639,12 +1639,12 @@ bool NetCvode::init_global() { // have the global cvode as its nvi field for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; - Memb_func* mf = memb_func + i; - if (mf->is_point && !nrn_is_artificial_[i]) { + const Memb_func& mf = memb_func[i]; + if (mf.is_point && !nrn_is_artificial_[i]) { Memb_list* ml = tml->ml; int j; for (j = 0; j < ml->nodecount; ++j) { - auto& datum = mf->hoc_mech ? ml->prop[j]->dparam[1] : ml->pdata[j][1]; + auto& datum = mf.hoc_mech ? ml->prop[j]->dparam[1] : ml->pdata[j][1]; auto* pp = datum.get(); pp->nvi_ = gcv_; } @@ -1723,11 +1723,10 @@ bool NetCvode::init_global() { for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; - Memb_func* mf = memb_func + i; + const Memb_func& mf = memb_func[i]; Memb_list* ml = tml->ml; - if (ml->nodecount && - (mf->current || mf->ode_count || mf->ode_matsol || mf->ode_spec || mf->state || - i == CAP || ba_candidate.count(i) == 1)) { + if (ml->nodecount && (mf.current || mf.ode_count || mf.ode_matsol || mf.ode_spec || + mf.state || i == CAP || ba_candidate.count(i) == 1)) { // maintain same order (not reversed) for // singly linked list built below int j; @@ -1773,11 +1772,10 @@ bool NetCvode::init_global() { // now list order is from 0 to n_memb_func for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; - Memb_func* mf = memb_func + i; + const Memb_func& mf = memb_func[i]; Memb_list* ml = tml->ml; - if (ml->nodecount && - (mf->current || mf->ode_count || mf->ode_matsol || mf->ode_spec || mf->state || - i == CAP || ba_candidate.count(i) == 1)) { + if (ml->nodecount && (mf.current || mf.ode_count || mf.ode_matsol || mf.ode_spec || + mf.state || i == CAP || ba_candidate.count(i) == 1)) { for (int j = 0; j < ml->nodecount; ++j) { int icell = cellnum[ml->nodelist[j]->v_node_index]; if (cvml[icell]->index != i) { @@ -1791,7 +1789,7 @@ bool NetCvode::init_global() { newml.nodelist[0] = ml->nodelist[j]; newml.nodeindices = new int[1]{ml->nodeindices[j]}; newml.prop = new Prop* [1] { ml->prop[j] }; - if (!mf->hoc_mech) { + if (!mf.hoc_mech) { newml.set_storage_offset(ml->get_storage_offset() + j); newml.pdata = new Datum* [1] { ml->pdata[j] }; } @@ -1807,12 +1805,12 @@ bool NetCvode::init_global() { // artifical cells have no integrator for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; - Memb_func* mf = memb_func + i; - if (mf->is_point) { + const Memb_func& mf = memb_func[i]; + if (mf.is_point) { Memb_list* ml = tml->ml; int j; for (j = 0; j < ml->nodecount; ++j) { - auto& datum = mf->hoc_mech ? ml->prop[j]->dparam[1] : ml->pdata[j][1]; + auto& datum = mf.hoc_mech ? ml->prop[j]->dparam[1] : ml->pdata[j][1]; auto* pp = datum.get(); if (nrn_is_artificial_[i] == 0) { int inode = ml->nodelist[j]->v_node_index; @@ -4465,8 +4463,8 @@ std::string NetCvode::statename(int is, int style) { assert(sym); return sym2name(sym); } else { - auto* s = hdp.retrieve(raw_ptr); - return s ? s->string() : "unknown"; + std::string s = hdp.retrieve(raw_ptr); + return !s.empty() ? s.c_str() : "unknown"; } }; int j{}; diff --git a/src/nrncvode/occvode.cpp b/src/nrncvode/occvode.cpp index bb2ec2db02..889f9fbc69 100644 --- a/src/nrncvode/occvode.cpp +++ b/src/nrncvode/occvode.cpp @@ -1,6 +1,5 @@ #include <../../nrnconf.h> #include -#include #include "nrn_ansi.h" #include "nrndae_c.h" #include "nrniv_mf.h" @@ -109,7 +108,6 @@ void Cvode::init_eqn() { NrnThread* _nt; CvMembList* cml; - Memb_func* mf; int i, j, zneq, zneq_v, zneq_cap_v; // printf("Cvode::init_eqn\n"); if (nthsizes_) { @@ -250,25 +248,25 @@ printf("%d Cvode::init_eqn id=%d neq_v_=%d #nonvint=%d #nonvint_extra=%d nvsize= // map the membrane mechanism ode state and dstate pointers int ieq = zneq_v; for (cml = z.cv_memb_list_; cml; cml = cml->next) { - mf = memb_func + cml->index; - if (!mf->ode_count) { + Memb_func& mf = memb_func[cml->index]; + if (!mf.ode_count) { continue; } for (auto& ml: cml->ml) { - if (int n; (n = mf->ode_count(cml->index)) > 0) { - // Note: if mf->hoc_mech then all cvode related + if (int n; (n = mf.ode_count(cml->index)) > 0) { + // Note: if mf.hoc_mech then all cvode related // callbacks are NULL (including ode_count) // See src/nrniv/hocmech.cpp. That won't change but // if it does, hocmech.cpp must follow all the // nrn_ode_..._t prototypes to avoid segfault // with Apple M1. for (j = 0; j < ml.nodecount; ++j) { - mf->ode_map(ml.prop[j], - ieq, - z.pv_.data() + ieq, - z.pvdot_.data() + ieq, - atv + ieq, - cml->index); + mf.ode_map(ml.prop[j], + ieq, + z.pv_.data() + ieq, + z.pvdot_.data() + ieq, + atv + ieq, + cml->index); ieq += n; } } @@ -284,9 +282,9 @@ void Cvode::new_no_cap_memb(CvodeThreadData& z, NrnThread* _nt) { z.no_cap_memb_ = nullptr; CvMembList* ncm{}; for (auto* cml = z.cv_memb_list_; cml; cml = cml->next) { - Memb_func* mf = memb_func + cml->index; + const Memb_func& mf = memb_func[cml->index]; // only point processes with currents are possibilities - if (!mf->is_point || !mf->current) { + if (!mf.is_point || !mf.current) { continue; } // count how many at no cap nodes @@ -324,7 +322,7 @@ void Cvode::new_no_cap_memb(CvodeThreadData& z, NrnThread* _nt) { assert(newml.nodelist[0] == ml.nodelist[i]); newml.nodeindices = new int[1]{ml.nodeindices[i]}; newml.prop = new Prop* [1] { ml.prop[i] }; - if (!mf->hoc_mech) { + if (!mf.hoc_mech) { // Danger: this is not stable w.r.t. permutation newml.set_storage_offset(ml.get_storage_offset() + i); newml.pdata = new Datum* [1] { ml.pdata[i] }; @@ -475,10 +473,10 @@ void Cvode::scatter_y(neuron::model_sorted_token const& sorted_token, double* y, // printf("%d scatter_y %d %d %g\n", nrnmpi_myid, tid, i, y[i]); } for (CvMembList* cml = z.cv_memb_list_; cml; cml = cml->next) { - Memb_func* mf = memb_func + cml->index; - if (mf->ode_synonym) { + const Memb_func& mf = memb_func[cml->index]; + if (mf.ode_synonym) { for (auto& ml: cml->ml) { - mf->ode_synonym(sorted_token, nrn_threads[tid], ml, cml->index); + mf.ode_synonym(sorted_token, nrn_threads[tid], ml, cml->index); } } } @@ -661,8 +659,8 @@ void Cvode::solvemem(neuron::model_sorted_token const& sorted_token, NrnThread* CvodeThreadData& z = CTD(nt->id); CvMembList* cml; for (cml = z.cv_memb_list_; cml; cml = cml->next) { // probably can start at 6 or hh - Memb_func* mf = memb_func + cml->index; - if (auto const ode_matsol = mf->ode_matsol; ode_matsol) { + const Memb_func& mf = memb_func[cml->index]; + if (auto const ode_matsol = mf.ode_matsol; ode_matsol) { for (auto& ml: cml->ml) { ode_matsol(sorted_token, nt, &ml, cml->index); if (errno && nrn_errno_check(cml->index)) { @@ -962,14 +960,15 @@ void Cvode::do_nonode(neuron::model_sorted_token const& sorted_token, NrnThread* CvodeThreadData& z = CTD(_nt->id); CvMembList* cml; for (cml = z.cv_memb_list_; cml; cml = cml->next) { - Memb_func* mf = memb_func + cml->index; - if (mf->state) { - for (auto& ml: cml->ml) { - if (!mf->ode_spec) { - mf->state(sorted_token, _nt, &ml, cml->index); - } else if (mf->singchan_) { - mf->singchan_(_nt, &ml, cml->index); - } + const Memb_func& mf = memb_func[cml->index]; + if (!mf.state) { + continue; + } + for (auto& ml: cml->ml) { + if (!mf.ode_spec) { + mf.state(sorted_token, _nt, &ml, cml->index); + } else if (mf.singchan_) { + mf.singchan_(_nt, &ml, cml->index); } } } diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index 8800663d1b..2af3fc458d 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -91,11 +91,15 @@ 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. -target_include_directories(nocmodl PRIVATE "${NRN_NMODL_GEN}" "${NRN_NMODL_SRC_DIR}") +# directory. TODO: (see also coreneuron) fix adding a dependency on CLI11::CLI11 when CLI11 is a +# submodule. Right now this doesn't work because the CLI11 targets are not exported/installed but +# coreneuron-core is. +get_target_property(CLI11_HEADER_DIRECTORY CLI11::CLI11 INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(nocmodl PRIVATE "${NRN_NMODL_GEN}" "${NRN_NMODL_SRC_DIR}" + "${CLI11_HEADER_DIRECTORY}") if(NRN_NMODL_CXX_FLAGS) target_compile_options(nocmodl PRIVATE ${NRN_NMODL_CXX_FLAGS}) endif() diff --git a/src/nrniv/kschan.cpp b/src/nrniv/kschan.cpp index 67ad2b0604..655d4b376a 100644 --- a/src/nrniv/kschan.cpp +++ b/src/nrniv/kschan.cpp @@ -399,7 +399,7 @@ static const char** ks_name(void* v) { ks->setname(gargstr(1)); } char** ps = hoc_temp_charptr(); - *ps = (char*) ks->name_.string(); + *ps = (char*) ks->name_.c_str(); return (const char**) ps; } @@ -409,7 +409,7 @@ static const char** ks_ion(void* v) { ks->setion(gargstr(1)); } char** ps = hoc_temp_charptr(); - *ps = (char*) ks->ion_.string(); + *ps = (char*) ks->ion_.c_str(); return (const char**) ps; } @@ -639,9 +639,9 @@ static double ks_pr(void* v) { Printf("%s type properties\n", hoc_object_name(ks->obj_)); Printf("name=%s is_point_=%s ion_=%s cond_model_=%d\n", - ks->name_.string(), + ks->name_.c_str(), (ks->is_point() ? "true" : "false"), - ks->ion_.string(), + ks->ion_.c_str(), ks->cond_model_); Printf(" ngate=%d nstate=%d nhhstate=%d nligand=%d ntrans=%d ivkstrans=%d iligtrans=%d\n", ks->ngate_, @@ -886,12 +886,12 @@ KSChan::KSChan(Object* obj, bool is_p) { gmax_deflt_ = 0.; erev_deflt_ = 0.; soffset_ = 4; // gmax, e, g, i before the first state in p array - const char* suffix = name_.string(); + const char* suffix = name_.c_str(); char unsuffix[100]; if (is_point()) { unsuffix[0] = '\0'; } else { - Sprintf(unsuffix, "_%s", name_.string()); + Sprintf(unsuffix, "_%s", name_.c_str()); } if (looksym(suffix)) { hoc_execerror(suffix, "already exists"); @@ -929,21 +929,21 @@ KSChan::KSChan(Object* obj, bool is_p) { } setcond(); sname_install(); - // printf("%s allowed in insert statement\n", name_.string()); + // printf("%s allowed in insert statement\n", name_.c_str()); } void KSChan::setname(const char* s) { // printf("KSChan::setname\n"); int i; - if (strcmp(s, name_.string()) == 0) { + if (strcmp(s, name_.c_str()) == 0) { return; } name_ = s; if (mechsym_) { char old_suffix[100]; i = 0; - while (strcmp(mechsym_->name, name_.string()) != 0 && looksym(name_.string())) { - Printf("KSChan::setname %s already in use\n", name_.string()); + while (strcmp(mechsym_->name, name_.c_str()) != 0 && looksym(name_.c_str())) { + Printf("KSChan::setname %s already in use\n", name_.c_str()); Sprintf(old_suffix, "%s%d", s, i); name_ = old_suffix; ++i; @@ -952,7 +952,7 @@ void KSChan::setname(const char* s) { // return; } Sprintf(old_suffix, "_%s", mechsym_->name); - const char* suffix = name_.string(); + const char* suffix = name_.c_str(); free(mechsym_->name); mechsym_->name = strdup(suffix); if (is_point()) { @@ -977,7 +977,7 @@ void KSChan::setname(const char* s) { sp->name = s1; } } - // printf("%s renamed to %s\n", old_suffix+1, name_.string()); + // printf("%s renamed to %s\n", old_suffix+1, name_.c_str()); } } @@ -1133,7 +1133,7 @@ void KSChan::update_prop() { std::string name{state(i)}; if (!is_point()) { // only called from set_single so never reached. name += "_"; - name += name_.string(); + name += name_.c_str(); } int j = i + soffset_; @@ -1151,7 +1151,7 @@ void KSChan::update_prop() { void KSChan::setion(const char* s) { // printf("KSChan::setion\n"); int i; - if (strcmp(ion_.string(), s) == 0) { + if (strcmp(ion_.c_str(), s) == 0) { return; } // before doing anything destructive, check if update_size is going to succeed below @@ -1160,7 +1160,7 @@ void KSChan::setion(const char* s) { // now we know update_size will succeed, we can start modifying member data Symbol* searchsym = (is_point() ? mechsym_ : NULL); - ion_ = new_ion.c_str(); + ion_ = new_ion; char buf[100]; int pdoff = ppoff_; int io = gmaxoffset_; @@ -1209,7 +1209,7 @@ void KSChan::setion(const char* s) { if (ion_sym_) { // there already is an ion if (strcmp(ion_sym_->name, buf) != 0) { // is it different // printf(" mechanism %s now uses %s instead of %s\n", - // name_.string(), sym->name, ion_sym_->name); + // name_.c_str(), sym->name, ion_sym_->name); ion_sym_ = sym; ion_consist(); } @@ -2294,7 +2294,7 @@ void KSChan::update_size() { void KSChan::alloc(Prop* prop) { // printf("KSChan::alloc nstate_=%d nligand_=%d\n", nstate_, nligand_); - // printf("KSChan::alloc %s param=%p\n", name_.string(), prop->param); + // printf("KSChan::alloc %s param=%p\n", name_.c_str(), prop->param); int j; assert(prop->param_size() == prop->param_num_vars()); // no array vars assert(prop->param_num_vars() == soffset_ + 2 * nstate_); diff --git a/src/nrniv/kschan.h b/src/nrniv/kschan.h index 02f4a868d8..de49789be5 100644 --- a/src/nrniv/kschan.h +++ b/src/nrniv/kschan.h @@ -2,10 +2,9 @@ #define kschan_h #include -#include #include "nrnoc2iv.h" #include "ivocvect.h" -#include "nrnunits_modern.h" +#include "nrnunits.h" #include "spmatrix.h" @@ -95,10 +94,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 @@ -329,10 +325,10 @@ class KSState { KSState(); virtual ~KSState(); const char* string() { - return name_.string(); + return name_.c_str(); } double f_; // normalized conductance - CopyString name_; + std::string name_; int index_; // into state_ array KSChan* ks_; Object* obj_; @@ -443,8 +439,8 @@ class KSChan { int mechtype_; public: - CopyString name_; // name of channel - CopyString ion_; // name of ion , "" means non-specific + std::string name_; // name of channel + std::string ion_; // name of ion , "" means non-specific double gmax_deflt_; double erev_deflt_; int cond_model_; diff --git a/src/nrniv/memory_usage.cpp b/src/nrniv/memory_usage.cpp index ff5eb2a3ce..a7b6766dc5 100644 --- a/src/nrniv/memory_usage.cpp +++ b/src/nrniv/memory_usage.cpp @@ -43,8 +43,7 @@ cache::ModelMemoryUsage memory_usage(const neuron::cache::Model& model) { MemoryUsage local_memory_usage() { return MemoryUsage{memory_usage(model()), memory_usage(neuron::cache::model), - detail::compute_defer_delete_storage_size(), - detail::compute_identifier_defer_delete_storage_size()}; + detail::compute_defer_delete_storage_size()}; } namespace detail { @@ -62,10 +61,6 @@ VectorMemoryUsage compute_defer_delete_storage_size(std::vector const* const } -VectorMemoryUsage compute_identifier_defer_delete_storage_size() { - return compute_defer_delete_storage_size(identifier_defer_delete_storage, sizeof(std::size_t)); -} - VectorMemoryUsage compute_defer_delete_storage_size() { return compute_defer_delete_storage_size(defer_delete_storage, sizeof(void*)); } @@ -105,7 +100,6 @@ std::string format_memory_usage(const MemoryUsage& usage) { const auto& model = usage.model; const auto& cache_model = usage.cache_model; const auto& stable_pointers = usage.stable_pointers; - const auto& stable_identifiers = usage.stable_identifiers; const auto& total = usage.compute_total(); const auto& summary = MemoryUsageSummary(usage); @@ -124,7 +118,6 @@ std::string format_memory_usage(const MemoryUsage& usage) { os << " threads " << format_memory_usage(cache_model.threads) << "\n"; os << " mechanisms " << format_memory_usage(cache_model.mechanisms) << "\n"; os << "deferred deletion \n"; - os << " stable_identifiers " << format_memory_usage(stable_identifiers) << "\n"; os << " stable_pointers " << format_memory_usage(stable_pointers) << "\n"; os << "\n"; os << "total " << format_memory_usage(total) << "\n"; diff --git a/src/nrniv/nrncore_write.cpp b/src/nrniv/nrncore_write.cpp index a3b5d8d94c..cd9550f0b7 100644 --- a/src/nrniv/nrncore_write.cpp +++ b/src/nrniv/nrncore_write.cpp @@ -200,8 +200,8 @@ static part1_ret part1() { for (int i = 0; i < n_memb_func; ++i) { int sz = nrn_prop_dparam_size_[i]; bbcore_dparam_size[i] = sz; - Memb_func* mf = memb_func + i; - if (mf && mf->dparam_semantics && sz && mf->dparam_semantics[sz - 1] == -3) { + const Memb_func& mf = memb_func[i]; + if (mf.dparam_semantics && sz && mf.dparam_semantics[sz - 1] == -3) { // cvode_ieq in NEURON but not CoreNEURON bbcore_dparam_size[i] = sz - 1; } 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/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index 4cc3e1c22e..cfe20eea35 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -3,7 +3,6 @@ #include #include -#include #if HAVE_IV #include "secbrows.h" @@ -763,7 +762,7 @@ void MechanismStandard::panel(const char* label) { hoc_pushx(0.0); pyactval = neuron::python::methods.callable_with_args(pyact_, 3); } else { - Sprintf(buf, "hoc_ac_ = %d %s", i, action_.string()); + Sprintf(buf, "hoc_ac_ = %d %s", i, action_.c_str()); } hoc_ivvaluerun_ex(sym->name, NULL, @@ -788,7 +787,7 @@ void MechanismStandard::panel(const char* label) { hoc_pushx(double(j)); pyactval = neuron::python::methods.callable_with_args(pyact_, 3); } else { - Sprintf(buf, "hoc_ac_ = %d %s", i, action_.string()); + Sprintf(buf, "hoc_ac_ = %d %s", i, action_.c_str()); } char buf2[200]; Sprintf(buf2, "%s[%d]", sym->name, j); @@ -1139,7 +1138,7 @@ void MechanismType_reg() { int* type_; int count_; int select_; - CopyString action_; + std::string action_; Object* pyact_; Section* sec_iter_; int inode_iter_; @@ -1316,11 +1315,8 @@ void MechanismType::menu() { hoc_ivbutton(s->name, NULL, pyactval); hoc_obj_unref(pyactval); } else { - Sprintf(buf, - "xbutton(\"%s\", \"hoc_ac_=%d %s\")\n", - s->name, - i, - mti_->action_.string()); + Sprintf( + buf, "xbutton(\"%s\", \"hoc_ac_=%d %s\")\n", s->name, i, mti_->action_.c_str()); oc.run(buf); } } diff --git a/src/nrniv/nrnmenu.h b/src/nrniv/nrnmenu.h index 59bd8d3754..f310394990 100644 --- a/src/nrniv/nrnmenu.h +++ b/src/nrniv/nrnmenu.h @@ -1,7 +1,6 @@ #ifndef nrnmenu_h #define nrnmenu_h -#include #include "ndatclas.h" class MechTypeImpl; @@ -39,7 +38,7 @@ class MechanismStandard: public Resource { int name_cnt_; int offset_; int vartype_; - CopyString action_; + std::string action_; Object* pyact_; Symbol** glosym_; void mschk(const char*); diff --git a/src/nrniv/shape.cpp b/src/nrniv/shape.cpp index 64f36f8988..389c17b1e7 100644 --- a/src/nrniv/shape.cpp +++ b/src/nrniv/shape.cpp @@ -878,7 +878,6 @@ ShapeScene::ShapeScene(SectionList* sl) r3b_ = new Rotate3Band(NULL, new RubberCallback(ShapeScene)(this, &ShapeScene::transform3d)); r3b_->ref(); observe(sl); - var_name_ = NULL; wk.style()->find_attribute("shape_beveljoin", beveljoin_); MenuItem* mi; @@ -961,9 +960,6 @@ ShapeScene::~ShapeScene() { Resource::unref(sg_); Resource::unref(r3b_); delete shape_changed_; - if (var_name_) { - delete var_name_; - } } void ShapeScene::erase_all() { @@ -1040,24 +1036,17 @@ PolyGlyph* ShapeScene::shape_section_list() { } void ShapeScene::name(const char* s) { - if (!var_name_) { - var_name_ = new CopyString(s); - } else { - *var_name_ = s; - } + var_name_ = s; } void ShapeScene::save_phase2(std::ostream& o) { - char buf[256]; - if (var_name_) { - if ((var_name_->string())[var_name_->length() - 1] == '.') { - Sprintf(buf, "%sappend(save_window_)", var_name_->string()); + if (!var_name_.empty()) { + if (var_name_.back() == '.') { + o << var_name_ << "append(save_window_)" << std::endl; } else { - Sprintf(buf, "%s = save_window_", var_name_->string()); + o << var_name_ << " = save_window_" << std::endl; } - o << buf << std::endl; - Sprintf(buf, "save_window_.save_name(\"%s\")", var_name_->string()); - o << buf << std::endl; + o << "save_window_.save_name(\"" << var_name_ << "\")" << std::endl; } Graph::save_phase2(o); } diff --git a/src/nrniv/shape.h b/src/nrniv/shape.h index f74de89d58..fdf0ccfc67 100644 --- a/src/nrniv/shape.h +++ b/src/nrniv/shape.h @@ -80,7 +80,7 @@ class ShapeScene: public Graph { // entire neuron SectionHandler* section_handler_; PolyGlyph* sg_; Rotate3Band* r3b_; - CopyString* var_name_; + std::string var_name_; ShapeChangeObserver* shape_changed_; }; diff --git a/src/nrniv/shapeplt.cpp b/src/nrniv/shapeplt.cpp index 27df1aa624..994cdddb11 100644 --- a/src/nrniv/shapeplt.cpp +++ b/src/nrniv/shapeplt.cpp @@ -768,7 +768,7 @@ void ShapePlotImpl::select_variable() { sc->ref(); while (sc->post_for(XYView::current_pick_view()->canvas()->window())) { Symbol* s; - s = hoc_table_lookup(sc->selected()->string(), hoc_built_in_symlist); + s = hoc_table_lookup(sc->selected().c_str(), hoc_built_in_symlist); if (s) { sp_->variable(s); break; diff --git a/src/nrniv/spaceplt.cpp b/src/nrniv/spaceplt.cpp index 8308e98232..11fa8ab7c4 100644 --- a/src/nrniv/spaceplt.cpp +++ b/src/nrniv/spaceplt.cpp @@ -4,7 +4,6 @@ #include -#include #include #if HAVE_IV #include "graph.h" @@ -112,7 +111,7 @@ class RangeVarPlot: public NoIVGraphVector { Section *begin_section_, *end_section_; float x_begin_, x_end_, origin_; SecPosList* sec_list_; - CopyString expr_; + std::string expr_; int shape_changed_; int struc_changed_; double d2root_; // distance to root of closest point to root @@ -441,7 +440,7 @@ void RangeVarPlot::request(Requisition& req) const { void RangeVarPlot::save(std::ostream& o) { char buf[256]; o << "objectvar rvp_" << std::endl; - Sprintf(buf, "rvp_ = new RangeVarPlot(\"%s\")", expr_.string()); + Sprintf(buf, "rvp_ = new RangeVarPlot(\"%s\")", expr_.c_str()); o << buf << std::endl; Sprintf(buf, "%s rvp_.begin(%g)", hoc_section_pathname(begin_section_), x_begin_); o << buf << std::endl; @@ -515,12 +514,12 @@ void RangeVarPlot::fill_pointers() { if (rexp_) { rexp_->fill(); } else { - sscanf(expr_.string(), "%[^[]", buf); + sscanf(expr_.c_str(), "%[^[]", buf); sym = hoc_lookup(buf); if (!sym) { return; } - Sprintf(buf, "%s(hoc_ac_)", expr_.string()); + Sprintf(buf, "%s(hoc_ac_)", expr_.c_str()); } int noexist = 0; // don't plot single points that don't exist bool does_exist; diff --git a/src/nrniv/vrecord.cpp b/src/nrniv/vrecord.cpp index f815e42afa..3100b1ffba 100644 --- a/src/nrniv/vrecord.cpp +++ b/src/nrniv/vrecord.cpp @@ -1,7 +1,6 @@ #include <../../nrnconf.h> #include -#include #if HAVE_IV #include "ivoc.h" #endif diff --git a/src/nrnmpi/bbsmpipack.cpp b/src/nrnmpi/bbsmpipack.cpp index f68c1edce0..0112a9530c 100644 --- a/src/nrnmpi/bbsmpipack.cpp +++ b/src/nrnmpi/bbsmpipack.cpp @@ -20,18 +20,7 @@ #include #include -#if 0 -#define guard(f) nrn_assert(f == MPI_SUCCESS) -#else -#define guard(f) \ - { \ - int _i = f; \ - if (_i != MPI_SUCCESS) { \ - printf("%s %d\n", #f, _i); \ - assert(0); \ - } \ - } -#endif +#define nrn_mpi_assert(arg) nrn_assert(arg == MPI_SUCCESS) #define nrnmpidebugleak 0 #define debug 0 @@ -69,7 +58,7 @@ static void unpack(void* buf, int count, int my_datatype, bbsmpibuf* r, const ch r->size); #endif assert(r->upkpos >= 0 && r->size >= r->upkpos); - guard(MPI_Unpack(r->buf, r->size, &r->upkpos, type, 2, MPI_INT, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &r->upkpos, type, 2, MPI_INT, nrn_bbs_comm)); #if debug printf("%d unpack r=%p size=%d upkpos=%d type[0]=%d datatype=%d type[1]=%d count=%d\n", nrnmpi_myid_bbs, @@ -93,7 +82,8 @@ static void unpack(void* buf, int count, int my_datatype, bbsmpibuf* r, const ch } assert(type[0] == my_datatype); assert(type[1] == count); - guard(MPI_Unpack(r->buf, r->size, &r->upkpos, buf, count, mytypes[my_datatype], nrn_bbs_comm)); + nrn_mpi_assert( + MPI_Unpack(r->buf, r->size, &r->upkpos, buf, count, mytypes[my_datatype], nrn_bbs_comm)); } void nrnmpi_upkbegin(bbsmpibuf* r) { @@ -111,12 +101,12 @@ void nrnmpi_upkbegin(bbsmpibuf* r) { hoc_execerror("subworld process with nhost > 0 cannot use", "the bulletin board"); } r->upkpos = 0; - guard(MPI_Unpack(r->buf, r->size, &r->upkpos, &p, 1, MPI_INT, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &r->upkpos, &p, 1, MPI_INT, nrn_bbs_comm)); if (p > r->size) { printf("\n %d nrnmpi_upkbegin keypos=%d size=%d\n", nrnmpi_myid_bbs, p, r->size); } assert(p <= r->size); - guard(MPI_Unpack(r->buf, r->size, &p, &type, 1, MPI_INT, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &p, &type, 1, MPI_INT, nrn_bbs_comm)); #if debug printf("%d nrnmpi_upkbegin type=%d keypos=%d\n", nrnmpi_myid_bbs, type, p); #endif @@ -230,7 +220,7 @@ void nrnmpi_pkbegin(bbsmpibuf* r) { printf( "%d nrnmpi_pkbegin %p size=%d pkposition=%d\n", nrnmpi_myid_bbs, r, r->size, r->pkposition); #endif - guard(MPI_Pack(&type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Pack(&type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); } void nrnmpi_enddata(bbsmpibuf* r) { @@ -240,7 +230,7 @@ void nrnmpi_enddata(bbsmpibuf* r) { #if debug printf("%d nrnmpi_enddata %p size=%d pkposition=%d\n", nrnmpi_myid_bbs, r, r->size, p); #endif - guard(MPI_Pack_size(1, MPI_INT, nrn_bbs_comm, &isize)); + nrn_mpi_assert(MPI_Pack_size(1, MPI_INT, nrn_bbs_comm, &isize)); oldsize = r->size; resize(r, r->pkposition + isize); #if debug @@ -248,7 +238,7 @@ void nrnmpi_enddata(bbsmpibuf* r) { printf("%d %p need %d more. end up with total of %d\n", nrnmpi_myid_bbs, r, isize, r->size); } #endif - guard(MPI_Pack(&type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Pack(&type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); #if debug printf("%d nrnmpi_enddata buf=%p size=%d pkposition=%d\n", nrnmpi_myid_bbs, @@ -256,7 +246,7 @@ void nrnmpi_enddata(bbsmpibuf* r) { r->size, r->pkposition); #endif - guard(MPI_Pack(&p, 1, MPI_INT, r->buf, r->size, &type, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Pack(&p, 1, MPI_INT, r->buf, r->size, &type, nrn_bbs_comm)); #if debug printf("%d after nrnmpi_enddata, %d was packed at beginning and 0 was packed before %d\n", nrnmpi_myid_bbs, @@ -278,8 +268,8 @@ static void pack(void* inbuf, int incount, int my_datatype, bbsmpibuf* r, const r->pkposition, e); #endif - guard(MPI_Pack_size(incount, mytypes[my_datatype], nrn_bbs_comm, &dsize)); - guard(MPI_Pack_size(2, MPI_INT, nrn_bbs_comm, &isize)); + nrn_mpi_assert(MPI_Pack_size(incount, mytypes[my_datatype], nrn_bbs_comm, &dsize)); + nrn_mpi_assert(MPI_Pack_size(2, MPI_INT, nrn_bbs_comm, &isize)); oldsize = r->size; resize(r, r->pkposition + dsize + isize); #if debug @@ -293,8 +283,8 @@ static void pack(void* inbuf, int incount, int my_datatype, bbsmpibuf* r, const #endif type[0] = my_datatype; type[1] = incount; - guard(MPI_Pack(type, 2, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); - guard(MPI_Pack( + nrn_mpi_assert(MPI_Pack(type, 2, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Pack( inbuf, incount, mytypes[my_datatype], r->buf, r->size, &r->pkposition, nrn_bbs_comm)); #if debug printf("%d pack done pkposition=%d\n", nrnmpi_myid_bbs, r->pkposition); @@ -357,9 +347,9 @@ void nrnmpi_bbssend(int dest, int tag, bbsmpibuf* r) { if (r) { assert(r->buf && r->keypos <= r->size); - guard(MPI_Send(r->buf, r->size, MPI_PACKED, dest, tag, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Send(r->buf, r->size, MPI_PACKED, dest, tag, nrn_bbs_comm)); } else { - guard(MPI_Send(NULL, 0, MPI_PACKED, dest, tag, nrn_bbs_comm)); + nrn_mpi_assert(MPI_Send(nullptr, 0, MPI_PACKED, dest, tag, nrn_bbs_comm)); } errno = 0; #if debug @@ -376,8 +366,8 @@ int nrnmpi_bbsrecv(int source, bbsmpibuf* r) { #if debug printf("%d nrnmpi_bbsrecv %p\n", nrnmpi_myid_bbs, r); #endif - guard(MPI_Probe(source, MPI_ANY_TAG, nrn_bbs_comm, &status)); - guard(MPI_Get_count(&status, MPI_PACKED, &size)); + nrn_mpi_assert(MPI_Probe(source, MPI_ANY_TAG, nrn_bbs_comm, &status)); + nrn_mpi_assert(MPI_Get_count(&status, MPI_PACKED, &size)); #if debug printf("%d nrnmpi_bbsrecv probe size=%d source=%d tag=%d\n", nrnmpi_myid_bbs, @@ -386,7 +376,8 @@ int nrnmpi_bbsrecv(int source, bbsmpibuf* r) { status.MPI_TAG); #endif resize(r, size); - guard(MPI_Recv(r->buf, r->size, MPI_PACKED, source, MPI_ANY_TAG, nrn_bbs_comm, &status)); + nrn_mpi_assert( + MPI_Recv(r->buf, r->size, MPI_PACKED, source, MPI_ANY_TAG, nrn_bbs_comm, &status)); errno = 0; /* Some MPI implementations limit tags to be less than full MPI_INT domain In the past we allowed TODO mesages to have tags > 20 (FIRSTID of src/parallel/bbssrv.h) @@ -425,14 +416,14 @@ int nrnmpi_bbssendrecv(int dest, int tag, bbsmpibuf* s, bbsmpibuf* r) { int nrnmpi_iprobe(int* size, int* tag, int* source) { int flag = 0; MPI_Status status; - guard(MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &flag, &status)); + nrn_mpi_assert(MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &flag, &status)); if (flag) { if (source) *source = status.MPI_SOURCE; if (tag) *tag = status.MPI_TAG; if (size) - guard(MPI_Get_count(&status, MPI_PACKED, size)); + nrn_mpi_assert(MPI_Get_count(&status, MPI_PACKED, size)); } return flag; } @@ -440,13 +431,13 @@ int nrnmpi_iprobe(int* size, int* tag, int* source) { void nrnmpi_probe(int* size, int* tag, int* source) { int flag = 0; MPI_Status status; - guard(MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &status)); + nrn_mpi_assert(MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &status)); if (source) *source = status.MPI_SOURCE; if (tag) *tag = status.MPI_TAG; if (size) - guard(MPI_Get_count(&status, MPI_PACKED, size)); + nrn_mpi_assert(MPI_Get_count(&status, MPI_PACKED, size)); } bbsmpibuf* nrnmpi_newbuf(int size) { diff --git a/src/nrnmpi/mpispike.cpp b/src/nrnmpi/mpispike.cpp index 317f27f7b9..c84e2d0ae1 100644 --- a/src/nrnmpi/mpispike.cpp +++ b/src/nrnmpi/mpispike.cpp @@ -23,6 +23,8 @@ #include #include +#define nrn_mpi_assert(arg) nrn_assert(arg == MPI_SUCCESS) + extern void nrnbbs_context_wait(); static int np; @@ -286,13 +288,10 @@ static int MPI_Alltoallv_sparse(void* sendbuf, int* rdispls, MPI_Datatype recvtype, MPI_Comm comm) { - int status; int myrank; int nranks; - status = MPI_Comm_rank(comm, &myrank); - assert(status == MPI_SUCCESS); - status = MPI_Comm_size(comm, &nranks); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Comm_rank(comm, &myrank)); + nrn_mpi_assert(MPI_Comm_size(comm, &nranks)); int rankp; for (rankp = 0; nranks > (1 << rankp); rankp++) @@ -302,10 +301,8 @@ static int MPI_Alltoallv_sparse(void* sendbuf, ptrdiff_t send_elsize; ptrdiff_t recv_elsize; - status = MPI_Type_get_extent(sendtype, &lb, &send_elsize); - assert(status == MPI_SUCCESS); - status = MPI_Type_get_extent(recvtype, &lb, &recv_elsize); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Type_get_extent(sendtype, &lb, &send_elsize)); + nrn_mpi_assert(MPI_Type_get_extent(recvtype, &lb, &recv_elsize)); MPI_Request* requests = (MPI_Request*) hoc_Emalloc(nranks * 2 * sizeof(MPI_Request)); hoc_malchk(); @@ -321,18 +318,16 @@ static int MPI_Alltoallv_sparse(void* sendbuf, continue; if (recvcnts[target] == 0) continue; - status = MPI_Irecv((static_cast(recvbuf)) + recv_elsize * rdispls[target], - recvcnts[target], - recvtype, - target, - ALLTOALLV_SPARSE_TAG, - comm, - &requests[n_requests++]); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Irecv((static_cast(recvbuf)) + recv_elsize * rdispls[target], + recvcnts[target], + recvtype, + target, + ALLTOALLV_SPARSE_TAG, + comm, + &requests[n_requests++])); } - status = MPI_Barrier(comm); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Barrier(comm)); for (ngrp = 0; ngrp < (1 << rankp); ngrp++) { int target = myrank ^ ngrp; @@ -340,22 +335,19 @@ static int MPI_Alltoallv_sparse(void* sendbuf, continue; if (sendcnts[target] == 0) continue; - status = MPI_Isend((static_cast(sendbuf)) + send_elsize * sdispls[target], - sendcnts[target], - sendtype, - target, - ALLTOALLV_SPARSE_TAG, - comm, - &requests[n_requests++]); - assert(status == MPI_SUCCESS); - } - - status = MPI_Waitall(n_requests, requests, MPI_STATUSES_IGNORE); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Isend((static_cast(sendbuf)) + send_elsize * sdispls[target], + sendcnts[target], + sendtype, + target, + ALLTOALLV_SPARSE_TAG, + comm, + &requests[n_requests++])); + } + + nrn_mpi_assert(MPI_Waitall(n_requests, requests, MPI_STATUSES_IGNORE)); free(requests); - status = MPI_Barrier(comm); - assert(status == MPI_SUCCESS); + nrn_mpi_assert(MPI_Barrier(comm)); return MPI_SUCCESS; } @@ -625,25 +617,26 @@ void nrnmpi_barrier() { MPI_Barrier(nrnmpi_comm); } -double nrnmpi_dbl_allreduce(double x, int type) { - double result; - MPI_Op t; - if (nrnmpi_numprocs < 2) { - return x; - } +static MPI_Op type2OP(int type) { if (type == 1) { - t = MPI_SUM; + return MPI_SUM; } else if (type == 2) { - t = MPI_MAX; + return MPI_MAX; } else { - t = MPI_MIN; + return MPI_MIN; } - MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, t, nrnmpi_comm); +} + +double nrnmpi_dbl_allreduce(double x, int type) { + if (nrnmpi_numprocs < 2) { + return x; + } + double result; + MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, type2OP(type), nrnmpi_comm); return result; } extern "C" void nrnmpi_dbl_allreduce_vec(double* src, double* dest, int cnt, int type) { - MPI_Op t; assert(src != dest); if (nrnmpi_numprocs < 2) { for (int i = 0; i < cnt; ++i) { @@ -651,56 +644,31 @@ extern "C" void nrnmpi_dbl_allreduce_vec(double* src, double* dest, int cnt, int } return; } - if (type == 1) { - t = MPI_SUM; - } else if (type == 2) { - t = MPI_MAX; - } else { - t = MPI_MIN; - } - MPI_Allreduce(src, dest, cnt, MPI_DOUBLE, t, nrnmpi_comm); + MPI_Allreduce(src, dest, cnt, MPI_DOUBLE, type2OP(type), nrnmpi_comm); return; } void nrnmpi_longdbl_allreduce_vec(longdbl* src, longdbl* dest, int cnt, int type) { - int i; - MPI_Op t; assert(src != dest); if (nrnmpi_numprocs < 2) { - for (i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; ++i) { dest[i] = src[i]; } return; } - if (type == 1) { - t = MPI_SUM; - } else if (type == 2) { - t = MPI_MAX; - } else { - t = MPI_MIN; - } - MPI_Allreduce(src, dest, cnt, MPI_LONG_DOUBLE, t, nrnmpi_comm); + MPI_Allreduce(src, dest, cnt, MPI_LONG_DOUBLE, type2OP(type), nrnmpi_comm); return; } void nrnmpi_long_allreduce_vec(long* src, long* dest, int cnt, int type) { - int i; - MPI_Op t; assert(src != dest); if (nrnmpi_numprocs < 2) { - for (i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; ++i) { dest[i] = src[i]; } return; } - if (type == 1) { - t = MPI_SUM; - } else if (type == 2) { - t = MPI_MAX; - } else { - t = MPI_MIN; - } - MPI_Allreduce(src, dest, cnt, MPI_LONG, t, nrnmpi_comm); + MPI_Allreduce(src, dest, cnt, MPI_LONG, type2OP(type), nrnmpi_comm); return; } diff --git a/src/nrnmpi/nrnmpi.cpp b/src/nrnmpi/nrnmpi.cpp index bea98bb84d..386e96ac89 100644 --- a/src/nrnmpi/nrnmpi.cpp +++ b/src/nrnmpi/nrnmpi.cpp @@ -24,11 +24,7 @@ extern double nrn_timeus(); #if NRNMPI #include -#define asrt(arg) nrn_assert(arg == MPI_SUCCESS) -#define USE_HPM 0 -#if USE_HPM -#include -#endif +#define nrn_mpi_assert(arg) nrn_assert(arg == MPI_SUCCESS) #if NRN_MUSIC #include "nrnmusicapi.h" @@ -118,12 +114,12 @@ for (i=0; i < *pargc; ++i) { #if (NRN_ENABLE_THREADS) int required = MPI_THREAD_SERIALIZED; int provided; - asrt(MPI_Init_thread(pargc, pargv, required, &provided)); + nrn_mpi_assert(MPI_Init_thread(pargc, pargv, required, &provided)); if (required > provided) { nrn_cannot_use_threads_and_mpi = 1; } #else - asrt(MPI_Init(pargc, pargv)); + nrn_mpi_assert(MPI_Init(pargc, pargv)); #endif nrnmpi_under_nrncontrol_ = 1; #if NRN_MUSIC @@ -134,20 +130,20 @@ for (i=0; i < *pargc; ++i) { #if NRN_MUSIC if (nrnmusic) { - asrt(MPI_Comm_dup(nrnmusic_comm, &nrnmpi_world_comm)); + nrn_mpi_assert(MPI_Comm_dup(nrnmusic_comm, &nrnmpi_world_comm)); } else { #else { #endif - asrt(MPI_Comm_dup(MPI_COMM_WORLD, &nrnmpi_world_comm)); + nrn_mpi_assert(MPI_Comm_dup(MPI_COMM_WORLD, &nrnmpi_world_comm)); } } grp_bbs = MPI_GROUP_NULL; grp_net = MPI_GROUP_NULL; - asrt(MPI_Comm_dup(nrnmpi_world_comm, &nrnmpi_comm)); - asrt(MPI_Comm_dup(nrnmpi_world_comm, &nrn_bbs_comm)); - asrt(MPI_Comm_rank(nrnmpi_world_comm, &nrnmpi_myid_world)); - asrt(MPI_Comm_size(nrnmpi_world_comm, &nrnmpi_numprocs_world)); + nrn_mpi_assert(MPI_Comm_dup(nrnmpi_world_comm, &nrnmpi_comm)); + nrn_mpi_assert(MPI_Comm_dup(nrnmpi_world_comm, &nrn_bbs_comm)); + nrn_mpi_assert(MPI_Comm_rank(nrnmpi_world_comm, &nrnmpi_myid_world)); + nrn_mpi_assert(MPI_Comm_size(nrnmpi_world_comm, &nrnmpi_numprocs_world)); nrnmpi_numprocs = nrnmpi_numprocs_bbs = nrnmpi_numprocs_world; nrnmpi_myid = nrnmpi_myid_bbs = nrnmpi_myid_world; nrnmpi_spike_initialize(); @@ -239,44 +235,44 @@ void nrnmpi_subworld_size(int n) { return; } if (nrnmpi_comm != MPI_COMM_NULL) { - asrt(MPI_Comm_free(&nrnmpi_comm)); + nrn_mpi_assert(MPI_Comm_free(&nrnmpi_comm)); nrnmpi_comm = MPI_COMM_NULL; } if (nrn_bbs_comm != MPI_COMM_NULL) { - asrt(MPI_Comm_free(&nrn_bbs_comm)); + nrn_mpi_assert(MPI_Comm_free(&nrn_bbs_comm)); nrn_bbs_comm = MPI_COMM_NULL; } if (grp_bbs != MPI_GROUP_NULL) { - asrt(MPI_Group_free(&grp_bbs)); + nrn_mpi_assert(MPI_Group_free(&grp_bbs)); grp_bbs = MPI_GROUP_NULL; } if (grp_net != MPI_GROUP_NULL) { - asrt(MPI_Group_free(&grp_net)); + nrn_mpi_assert(MPI_Group_free(&grp_net)); grp_net = MPI_GROUP_NULL; } MPI_Group wg; - asrt(MPI_Comm_group(nrnmpi_world_comm, &wg)); + nrn_mpi_assert(MPI_Comm_group(nrnmpi_world_comm, &wg)); int r = nrnmpi_myid_world; /* special cases */ if (n == 1) { - asrt(MPI_Group_incl(wg, 1, &r, &grp_net)); - asrt(MPI_Comm_dup(nrnmpi_world_comm, &nrn_bbs_comm)); - asrt(MPI_Comm_create(nrnmpi_world_comm, grp_net, &nrnmpi_comm)); - asrt(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); - asrt(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); - asrt(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); - asrt(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); + nrn_mpi_assert(MPI_Group_incl(wg, 1, &r, &grp_net)); + nrn_mpi_assert(MPI_Comm_dup(nrnmpi_world_comm, &nrn_bbs_comm)); + nrn_mpi_assert(MPI_Comm_create(nrnmpi_world_comm, grp_net, &nrnmpi_comm)); + nrn_mpi_assert(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); + nrn_mpi_assert(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); + nrn_mpi_assert(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); + nrn_mpi_assert(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); nrnmpi_subworld_id = nrnmpi_myid_bbs; nrnmpi_numprocs_subworld = nrnmpi_numprocs_bbs; } else if (n == nrnmpi_numprocs_world) { - asrt(MPI_Group_incl(wg, 1, &r, &grp_bbs)); - asrt(MPI_Comm_dup(nrnmpi_world_comm, &nrnmpi_comm)); - asrt(MPI_Comm_create(nrnmpi_world_comm, grp_bbs, &nrn_bbs_comm)); - asrt(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); - asrt(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); + nrn_mpi_assert(MPI_Group_incl(wg, 1, &r, &grp_bbs)); + nrn_mpi_assert(MPI_Comm_dup(nrnmpi_world_comm, &nrnmpi_comm)); + nrn_mpi_assert(MPI_Comm_create(nrnmpi_world_comm, grp_bbs, &nrn_bbs_comm)); + nrn_mpi_assert(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); + nrn_mpi_assert(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); if (r == 0) { - asrt(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); - asrt(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); + nrn_mpi_assert(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); + nrn_mpi_assert(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); } else { nrnmpi_myid_bbs = -1; nrnmpi_numprocs_bbs = -1; @@ -300,21 +296,21 @@ void nrnmpi_subworld_size(int n) { range[1] = nw - 1; } range[2] = 1; /* stride */ - asrt(MPI_Group_range_incl(wg, 1, &range, &grp_net)); - asrt(MPI_Comm_create(nrnmpi_world_comm, grp_net, &nrnmpi_comm)); - asrt(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); - asrt(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); + nrn_mpi_assert(MPI_Group_range_incl(wg, 1, &range, &grp_net)); + nrn_mpi_assert(MPI_Comm_create(nrnmpi_world_comm, grp_net, &nrnmpi_comm)); + nrn_mpi_assert(MPI_Comm_rank(nrnmpi_comm, &nrnmpi_myid)); + nrn_mpi_assert(MPI_Comm_size(nrnmpi_comm, &nrnmpi_numprocs)); /* nrn_bbs_com ranks stride is nrnmpi_numprocs */ /* only rank 0 of each subworld participates in nrn_bbs_comm */ range[0] = 0; /* first world rank in nrn_bbs_comm */ range[1] = (nb - 1) * n; /* last world rank in nrn_bbs_comm */ range[2] = n; /* stride */ - asrt(MPI_Group_range_incl(wg, 1, &range, &grp_bbs)); - asrt(MPI_Comm_create(nrnmpi_world_comm, grp_bbs, &nrn_bbs_comm)); + nrn_mpi_assert(MPI_Group_range_incl(wg, 1, &range, &grp_bbs)); + nrn_mpi_assert(MPI_Comm_create(nrnmpi_world_comm, grp_bbs, &nrn_bbs_comm)); if (r % n == 0) { /* only rank 0 participates in nrn_bbs_comm */ - asrt(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); - asrt(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); + nrn_mpi_assert(MPI_Comm_rank(nrn_bbs_comm, &nrnmpi_myid_bbs)); + nrn_mpi_assert(MPI_Comm_size(nrn_bbs_comm, &nrnmpi_numprocs_bbs)); } else { nrnmpi_myid_bbs = -1; nrnmpi_numprocs_bbs = -1; @@ -326,7 +322,7 @@ void nrnmpi_subworld_size(int n) { } } nrnmpi_subworld_change_cnt++; - asrt(MPI_Group_free(&wg)); + nrn_mpi_assert(MPI_Group_free(&wg)); } /* so src/nrnpython/inithoc.cpp does not have to include a c++ mpi.h */ diff --git a/src/nrnoc/cabvars.h b/src/nrnoc/cabvars.h index 436239454d..9c9d6c879d 100644 --- a/src/nrnoc/cabvars.h +++ b/src/nrnoc/cabvars.h @@ -73,6 +73,6 @@ extern void morph_alloc(Prop*); #endif -extern Memb_func* memb_func; +extern std::vector memb_func; -#endif // NRN_CABVARS_H \ No newline at end of file +#endif // NRN_CABVARS_H diff --git a/src/nrnoc/container.cpp b/src/nrnoc/container.cpp index 15c68091aa..a493a2f5b5 100644 --- a/src/nrnoc/container.cpp +++ b/src/nrnoc/container.cpp @@ -18,13 +18,8 @@ Model::Model() { // needs some re-organisation if we ever want to support multiple Model instances assert(!container::detail::defer_delete_storage); container::detail::defer_delete_storage = &m_ptrs_for_deferred_deletion; - assert(!container::detail::identifier_defer_delete_storage); - container::detail::identifier_defer_delete_storage = &m_identifier_ptrs_for_deferred_deletion; } Model::~Model() { - assert(container::detail::identifier_defer_delete_storage == - &m_identifier_ptrs_for_deferred_deletion); - container::detail::identifier_defer_delete_storage = nullptr; assert(container::detail::defer_delete_storage == &m_ptrs_for_deferred_deletion); container::detail::defer_delete_storage = nullptr; std::for_each(m_ptrs_for_deferred_deletion.begin(), @@ -96,8 +91,6 @@ std::ostream& operator<<(std::ostream& os, generic_data_handle const& dh) { } } // namespace neuron::container namespace neuron::container::detail { -// See neuron/container/soa_identifier.hpp -std::vector>* identifier_defer_delete_storage{}; // See neuron/container/soa_container.hpp std::vector* defer_delete_storage{}; } // namespace neuron::container::detail 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 bb5c844e2f..5ed479a2a6 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -135,7 +135,7 @@ extern Symlist* nrn_load_dll_called_; extern int nrn_load_dll_recover_error(); extern void nrn_load_name_check(const char* name); static int memb_func_size_; -Memb_func* memb_func; +std::vector memb_func; std::vector memb_list; short* memb_order_; Symbol** pointsym; @@ -324,9 +324,9 @@ void hoc_last_init(void) { Fprintf(stderr, "%s\n", banner); IGNORE(fflush(stderr)); } - memb_func_size_ = 30; + memb_func_size_ = 30; // initial allocation size memb_list.reserve(memb_func_size_); - memb_func = (Memb_func*) ecalloc(memb_func_size_, sizeof(Memb_func)); + memb_func.resize(memb_func_size_); // we directly resize because it is used below pointsym = (Symbol**) ecalloc(memb_func_size_, sizeof(Symbol*)); point_process = (Point_process**) ecalloc(memb_func_size_, sizeof(Point_process*)); pnt_map = static_cast(ecalloc(memb_func_size_, sizeof(char))); @@ -460,16 +460,17 @@ void nrn_register_mech_common(const char** m, nrn_init_t initialize, int nrnpointerindex, /* if -1 then there are none */ int vectorized) { + // initialize at first entry, it will be incremented at exit of the function static int type = 2; /* 0 unused, 1 for cable section */ int j, k, modltype, pindx, modltypemax; Symbol* s; const char** m2; nrn_load_name_check(m[1]); - if (type >= memb_func_size_) { + // we exhausted the allocated space in the tables for the mechanism type data + // so reallocate memb_func_size_ += 20; - memb_func = (Memb_func*) erealloc(memb_func, memb_func_size_ * sizeof(Memb_func)); pointsym = (Symbol**) erealloc(pointsym, memb_func_size_ * sizeof(Symbol*)); point_process = (Point_process**) erealloc(point_process, memb_func_size_ * sizeof(Point_process*)); @@ -525,6 +526,7 @@ void nrn_register_mech_common(const char** m, assert(type >= memb_list.size()); memb_list.resize(type + 1); + memb_func.resize(type + 1); nrn_prop_param_size_[type] = 0; /* fill in later */ nrn_prop_dparam_size_[type] = 0; /* fill in later */ nrn_dparam_ptr_start_[type] = 0; /* fill in later */ @@ -1111,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/nrnoc/membfunc.h b/src/nrnoc/membfunc.h index 3dc7644fdc..7e21d5859f 100644 --- a/src/nrnoc/membfunc.h +++ b/src/nrnoc/membfunc.h @@ -135,9 +135,16 @@ inline std::size_t vext_pseudoindex() { } // namespace neuron::extracellular #endif -#define nrnocCONST 1 -#define DEP 2 -#define STATE 3 /*See init.cpp and cabvars.h for order of nrnocCONST, DEP, and STATE */ +#define nrnocCONST 1 // PARAMETER +#define DEP 2 // ASSIGNED +#define STATE 3 /* STATE: See init.cpp and cabvars.h for order of nrnocCONST, DEP, and STATE */ +#define NRNPOINTER \ + 4 /* added on to list of mechanism variables.These are \ +pointers which connect variables from other mechanisms via the _ppval array. \ +*/ + +#define _AMBIGUOUS 5 // for Ions +#define RAND 6 // RANDOM #define BEFORE_INITIAL 0 #define AFTER_INITIAL 1 @@ -152,7 +159,7 @@ typedef struct BAMech { } BAMech; extern BAMech** bamech_; -extern Memb_func* memb_func; +extern std::vector memb_func; extern int n_memb_func; extern int* nrn_prop_param_size_; extern int* nrn_prop_dparam_size_; @@ -161,12 +168,6 @@ extern std::vector memb_list; /* for finitialize, order is same up through extracellular, then ions, then mechanisms that write concentrations, then all others. */ extern short* memb_order_; -#define NRNPOINTER \ - 4 /* added on to list of mechanism variables.These are \ -pointers which connect variables from other mechanisms via the _ppval array. \ -*/ - -#define _AMBIGUOUS 5 namespace neuron::mechanism { template diff --git a/src/nrnoc/section.h b/src/nrnoc/section.h index 18e97cb4f9..0f496d1f46 100644 --- a/src/nrnoc/section.h +++ b/src/nrnoc/section.h @@ -106,6 +106,7 @@ struct Node { // neuron::container::handle::Node, but as an intermediate measure we can // add one of those as a member and forward some access/modifications to it. neuron::container::Node::owning_handle _node_handle{neuron::model().node_data()}; + [[nodiscard]] auto id() { return _node_handle.id(); } 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/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 1563b6bb2d..38c225d007 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -2599,11 +2599,11 @@ void remake_pmech_types() { void nrnpy_reg_mech(int type) { int i; char* s; - Memb_func* mf = memb_func + type; + Memb_func& mf = memb_func[type]; if (!nrnmodule_) { return; } - if (mf->is_point) { + if (mf.is_point) { if (nrn_is_artificial_[type] == 0) { Symlist* sl = nrn_pnt_template_[type]->symtable; Symbol* s = hoc_table_lookup("get_segment", sl); @@ -2615,7 +2615,7 @@ void nrnpy_reg_mech(int type) { } return; } - s = mf->sym->name; + s = mf.sym->name; // printf("nrnpy_reg_mech %s %d\n", s, type); if (PyDict_GetItemString(pmech_types, s)) { hoc_execerror(s, "mechanism already exists"); @@ -2623,8 +2623,8 @@ void nrnpy_reg_mech(int type) { Py_INCREF(pmech_generic_type); PyModule_AddObject(nrnmodule_, s, (PyObject*) pmech_generic_type); PyDict_SetItemString(pmech_types, s, Py_BuildValue("i", type)); - for (i = 0; i < mf->sym->s_varn; ++i) { - Symbol* sym = mf->sym->u.ppsym[i]; + for (i = 0; i < mf.sym->s_varn; ++i) { + Symbol* sym = mf.sym->u.ppsym[i]; rangevars_add(sym); } } diff --git a/src/nrnpython/rxd.cpp b/src/nrnpython/rxd.cpp index 0e9f599303..5c1117c4a3 100644 --- a/src/nrnpython/rxd.cpp +++ b/src/nrnpython/rxd.cpp @@ -20,9 +20,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; /* @@ -775,10 +773,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/nrnassrt.h b/src/oc/nrnassrt.h index d7b5a9338d..abd026ae66 100644 --- a/src/oc/nrnassrt.h +++ b/src/oc/nrnassrt.h @@ -12,44 +12,21 @@ has side effects which need to be executed regardles of NDEBUG. #if defined(hocassrt_h) /* hoc_execerror form */ #include "oc_ansi.h" -#if defined(__STDC__) #define nrn_assert(ex) \ - { \ + do { \ if (!(ex)) { \ fprintf(stderr, "Assertion failed: file %s, line %d\n", __FILE__, __LINE__); \ - hoc_execerror(#ex, (char*) 0); \ + hoc_execerror(#ex, nullptr); \ } \ - } -#else -#define nrn_assert(ex) \ - { \ - if (!(ex)) { \ - fprintf(stderr, "Assertion failed: file %s, line %d\n", __FILE__, __LINE__); \ - hoc_execerror("ex", (char*) 0); \ - } \ - } -#endif - + } while (0) #else /* abort form */ - -#if defined(__STDC__) #define nrn_assert(ex) \ - { \ + do { \ if (!(ex)) { \ fprintf(stderr, "Assertion failed: file %s, line %d\n", __FILE__, __LINE__); \ abort(); \ } \ - } -#else -#define nrn_assert(ex) \ - { \ - if (!(ex)) { \ - fprintf(stderr, "Assertion failed: file %s, line %d\n", __FILE__, __LINE__); \ - abort(); \ - } \ - } -#endif - + } while (0) #endif 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 diff --git a/test/unit_tests/container/container.cpp b/test/unit_tests/container/container.cpp index a44af53261..4ebadf1624 100644 --- a/test/unit_tests/container/container.cpp +++ b/test/unit_tests/container/container.cpp @@ -150,20 +150,6 @@ TEST_CASE("soa::get_num_variables", "[Neuron][data_structures]") { CHECK(data.get_num_variables() == 1ul); } -TEST_CASE("Identifier defer delete ", "[Neuron][internal][data_structures]") { - storage data; - - REQUIRE(detail::identifier_defer_delete_storage != nullptr); - auto usage_before = detail::compute_identifier_defer_delete_storage_size(); - { owning_handle instance{data}; } - auto usage_after = detail::compute_identifier_defer_delete_storage_size(); - - CHECK(usage_after.size - usage_before.size > 0); - CHECK(usage_after.capacity > 0); - CHECK(usage_before.size <= usage_before.capacity); - CHECK(usage_after.size <= usage_after.capacity); -} - TEST_CASE("defer delete storage pointer", "[Neuron][internal][data_structures]") { REQUIRE(detail::defer_delete_storage != nullptr); @@ -279,7 +265,7 @@ neuron::container::MemoryUsage dummy_memory_usage() { auto stable_pointers = neuron::container::VectorMemoryUsage(7, 17); auto stable_identifiers = neuron::container::VectorMemoryUsage(8, 18); - auto memory_usage = MemoryUsage{model, cache_model, stable_pointers, stable_identifiers}; + auto memory_usage = MemoryUsage{model, cache_model, stable_pointers}; return memory_usage; } @@ -288,8 +274,8 @@ neuron::container::MemoryUsage dummy_memory_usage() { TEST_CASE("total memory usage", "[Neuron][internal][data_structures]") { auto memory_usage = dummy_memory_usage(); auto total = memory_usage.compute_total(); - CHECK(total.size == (8 * 9) / 2); - CHECK(total.capacity == total.size + 8 * 10); + CHECK(total.size == (7 * 8) / 2); + CHECK(total.capacity == total.size + 7 * 10); } TEST_CASE("memory usage summary", "[Neuron][data_structures]") { diff --git a/test/unit_tests/container/node.cpp b/test/unit_tests/container/node.cpp index 0825f0bc5f..263db0c51a 100644 --- a/test/unit_tests/container/node.cpp +++ b/test/unit_tests/container/node.cpp @@ -273,16 +273,6 @@ TEST_CASE("SOA-backed Node structure", "[Neuron][data_structures][node]") { } } } - GIVEN("A node that is deleted without an active deferred-deletion vector") { - auto* const old = std::exchange(neuron::container::detail::identifier_defer_delete_storage, - nullptr); - // Because identifier_defer_delete_storage is nullptr, deleting `node` will delete the - // heap-allocated std::size_t that the data handles depend on. This touches an otherwise - // uncovered code path in soa_identifier.hpp. Meaningfully checking the right code path was - // followed seems excessively complicated. - { ::Node node{}; } - neuron::container::detail::identifier_defer_delete_storage = old; - } GIVEN("A series of nodes with increasing integer voltages") { using neuron::test::get_node_voltages; auto nodes_and_voltages = neuron::test::get_nodes_and_reference_voltages(); diff --git a/test/unit_tests/matrix.cpp b/test/unit_tests/matrix.cpp index e211de50a7..e4572169e4 100644 --- a/test/unit_tests/matrix.cpp +++ b/test/unit_tests/matrix.cpp @@ -202,7 +202,7 @@ SCENARIO("A Matrix", "[neuron_ivoc][OcMatrix]") { { IvocVect v(3); m.getdiag(-2, &v); - REQUIRE(v.vec()[2] == Catch::Detail::Approx(1.)); + REQUIRE(v.vec()[2] == Catch::Detail::Approx(1.0)); v.vec() = {1., 0., 0.}; m.setdiag(2, &v); REQUIRE(compareMatrix(m, {{42., 72., 1.}, {72., 114., 114.}, {1., 114., 2.}})); @@ -393,7 +393,7 @@ SCENARIO("A Matrix", "[neuron_ivoc][OcMatrix]") { v.vec() = {0., 1., 2.}; m.setdiag(-1, &v); REQUIRE(compareMatrix(m, {{1., 2., 3.}, {1., 2., 2.}, {3., 2., 3.}})); - } + }https://maths.anu.edu.au/files/CMAProcVol32-Complete.pdf { IvocVect v(3); v.vec() = {1, 2, 3};