From 62ee1d2d49cc1a8c9089f57e828fa92465394db2 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Mon, 11 Dec 2023 11:39:57 +0100 Subject: [PATCH] Activate usecases during CI. --- .github/workflows/nmodl-ci.yml | 11 ++++++++++ CMakeLists.txt | 6 ++++++ test/usecases/CMakeLists.txt | 7 +++++++ test/usecases/leonhard/leonhard.mod | 16 +++++++++++++++ test/usecases/leonhard/simulate.py | 31 +++++++++++++++++++++++++++++ test/usecases/run_test.sh | 14 +++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 test/usecases/CMakeLists.txt create mode 100644 test/usecases/leonhard/leonhard.mod create mode 100644 test/usecases/leonhard/simulate.py create mode 100755 test/usecases/run_test.sh diff --git a/.github/workflows/nmodl-ci.yml b/.github/workflows/nmodl-ci.yml index 40932e8c5f..bb982399c5 100644 --- a/.github/workflows/nmodl-ci.yml +++ b/.github/workflows/nmodl-ci.yml @@ -39,6 +39,9 @@ jobs: # Hyphens here will be replaced with commas before the value is # passed to NMODL_SANITIZERS sanitizer: address-leak + - config: + os: ubuntu-22.04 + enable_usecases: On - config: flag_warnings: ON os: ubuntu-22.04 @@ -80,6 +83,11 @@ jobs: python3 -m pip install -U pip setuptools python3 -m pip install --user -r requirements.txt + - name: Install neuron-nightly + if: ${{matrix.config.enable_usecases == 'On'}} + run: | + python3 -m pip install neuron-nightly + - name: Register compiler warning problem matcher if: ${{matrix.config.flag_warnings == 'ON'}} run: echo "::add-matcher::.github/problem-matchers/gcc.json" @@ -104,6 +112,9 @@ jobs: -Wno-sign-compare \ -Wno-overloaded-virtual") fi + if [[ -n "${{matrix.config.enable_usecases}}" ]]; then + cmake_args+=(-DNMODL_ENABLE_USECASES=${{matrix.config.enable_usecases}}) + fi if [[ -n "${{matrix.config.sanitizer}}" ]]; then cmake_args+=(-DCMAKE_BUILD_TYPE=Custom \ -DCMAKE_CXX_FLAGS="-O1 -g" \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a98839831..3c186e6e33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) # ============================================================================= option(NMODL_ENABLE_PYTHON_BINDINGS "Enable pybind11 based python bindings" ON) option(NMODL_ENABLE_TESTS "Enable build of tests" ON) +option(NMODL_ENABLE_USECASES + "If building tests, additionally enable build of usecase tests. Requires neuron." OFF) set(NMODL_EXTRA_CXX_FLAGS "" CACHE STRING "Add extra compile flags for NMODL sources") @@ -207,6 +209,10 @@ if(NOT NMODL_AS_SUBPROJECT AND NMODL_ENABLE_TESTS) include(CTest) add_subdirectory(test/unit) add_subdirectory(test/integration) + + if(NMODL_ENABLE_USECASES) + add_subdirectory(test/usecases) + endif() endif() # ============================================================================= diff --git a/test/usecases/CMakeLists.txt b/test/usecases/CMakeLists.txt new file mode 100644 index 0000000000..cdf8da45c6 --- /dev/null +++ b/test/usecases/CMakeLists.txt @@ -0,0 +1,7 @@ +set(NMODL_USECASE_DIRS leonhard) + +foreach(usecase ${NMODL_USECASE_DIRS}) + add_test(NAME usecase_${usecase} + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run_test.sh ${CMAKE_BINARY_DIR}/bin/nmodl + ${CMAKE_CURRENT_SOURCE_DIR}/${usecase}) +endforeach() diff --git a/test/usecases/leonhard/leonhard.mod b/test/usecases/leonhard/leonhard.mod new file mode 100644 index 0000000000..eef4b5476f --- /dev/null +++ b/test/usecases/leonhard/leonhard.mod @@ -0,0 +1,16 @@ +NEURON { + SUFFIX leonhard +} + +STATE { x } + +INITIAL { + x = 42 +} + +BREAKPOINT { + SOLVE dX METHOD cnexp +} + +DERIVATIVE dX { x' = -x } + diff --git a/test/usecases/leonhard/simulate.py b/test/usecases/leonhard/simulate.py new file mode 100644 index 0000000000..faad1daa32 --- /dev/null +++ b/test/usecases/leonhard/simulate.py @@ -0,0 +1,31 @@ +import os + +print(f"{os.environ['NEURON_MODULE_OPTIONS'] = }") + +import numpy as np + +from neuron import h, gui +from neuron.units import ms + +nseg = 1 + +s = h.Section() +s.insert("leonhard") +s.nseg = nseg + +x_hoc = h.Vector().record(s(0.5)._ref_x_leonhard) +t_hoc = h.Vector().record(h._ref_t) + +h.stdinit() +h.tstop = 5.0 * ms +h.run() + +x = np.array(x_hoc.as_numpy()) +t = np.array(t_hoc.as_numpy()) + +x0 = 42.0 +x_exact = 42.0 * np.exp(-t) +rel_err = np.abs(x - x_exact) / x_exact + +assert np.all(rel_err < 1e-12) +print("leonhard: success") diff --git a/test/usecases/run_test.sh b/test/usecases/run_test.sh new file mode 100755 index 0000000000..521a55434b --- /dev/null +++ b/test/usecases/run_test.sh @@ -0,0 +1,14 @@ +#! /usr/bin/env bash +set -e + +nmodl="$1" +usecase_dir="$2" + +pushd "${usecase_dir}" + +rm -r x86_64 tmp || true + +nrnivmodl -nmodl "${nmodl}" +x86_64/special simulate.py + +popd