Skip to content

Commit

Permalink
Backport #3093
Browse files Browse the repository at this point in the history
- We were commenting TABLE statement from hh.mod as TABLE
  statement was not supported in mod2c.
- NMODL on CoreNEURON side supports TABLE statements also
  on GPU side.
- Hence, we can remove the CMake toggling logic for TABLE.
- Also update the references for tests in ringtest and testcorenrn repos

fixes #1764
  • Loading branch information
pramodk authored and JCGoran committed Oct 31, 2024
1 parent 078a34a commit 16ab91d
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 218 deletions.
9 changes: 2 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -713,22 +713,17 @@ endif()
# =============================================================================
if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY)
set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ GLOBAL minf/ RANGE minf/'")
set(TABLE_VAR_TOGGLE_COMMAND "'s/ TABLE minf/ :TABLE minf/'")
else()
set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ RANGE minf/ GLOBAL minf/'")
set(TABLE_VAR_TOGGLE_COMMAND "'s/ :TABLE minf/ TABLE minf/'")
endif()
separate_arguments(GLOBAL_VAR_TOGGLE_COMMAND UNIX_COMMAND "${GLOBAL_VAR_TOGGLE_COMMAND}")
separate_arguments(TABLE_VAR_TOGGLE_COMMAND UNIX_COMMAND "${TABLE_VAR_TOGGLE_COMMAND}")
add_custom_target(
hh_update
COMMAND sed ${GLOBAL_VAR_TOGGLE_COMMAND} ${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod >
${CMAKE_BINARY_DIR}/hh.mod.1
COMMAND sed ${TABLE_VAR_TOGGLE_COMMAND} ${CMAKE_BINARY_DIR}/hh.mod.1 >
${CMAKE_BINARY_DIR}/hh.mod.2
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.2
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.1
${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod
COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1 ${CMAKE_BINARY_DIR}/hh.mod.2
COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1
COMMENT "Update hh.mod for CoreNEURON compatibility"
VERBATIM)
add_dependencies(nrniv_lib hh_update)
Expand Down
125 changes: 125 additions & 0 deletions src/coreneuron/mechanism/mech/modfile/hh.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
TITLE hh.mod squid sodium, potassium, and leak channels

COMMENT
This is the original Hodgkin-Huxley treatment for the set of sodium,
potassium, and leakage channels found in the squid giant axon membrane.
("A quantitative description of membrane current and its application
conduction and excitation in nerve" J.Physiol. (Lond.) 117:500-544 (1952).)
Membrane voltage is in absolute mV and has been reversed in polarity
from the original HH convention and shifted to reflect a resting potential
of -65 mV.
Remember to set celsius=6.3 (or whatever) in your HOC file.
See squid.hoc for an example of a simulation using this model.
SW Jaslove 6 March, 1992
ENDCOMMENT

UNITS {
(mA) = (milliamp)
(mV) = (millivolt)
(S) = (siemens)
}

? interface
NEURON {
SUFFIX hh
USEION na READ ena WRITE ina
USEION k READ ek WRITE ik
NONSPECIFIC_CURRENT il
RANGE gnabar, gkbar, gl, el, gna, gk
:GLOBAL minf, hinf, ninf, mtau, htau, ntau
RANGE minf, hinf, ninf, mtau, htau, ntau
THREADSAFE : assigned GLOBALs will be per thread
}

PARAMETER {
gnabar = .12 (S/cm2) <0,1e9>
gkbar = .036 (S/cm2) <0,1e9>
gl = .0003 (S/cm2) <0,1e9>
el = -54.3 (mV)
}

STATE {
m h n
}

ASSIGNED {
v (mV)
celsius (degC)
ena (mV)
ek (mV)

gna (S/cm2)
gk (S/cm2)
ina (mA/cm2)
ik (mA/cm2)
il (mA/cm2)
minf hinf ninf
mtau (ms) htau (ms) ntau (ms)
}

? currents
BREAKPOINT {
SOLVE states METHOD cnexp
gna = gnabar*m*m*m*h
ina = gna*(v - ena)
gk = gkbar*n*n*n*n
ik = gk*(v - ek)
il = gl*(v - el)
}


INITIAL {
rates(v)
m = minf
h = hinf
n = ninf
}

? states
DERIVATIVE states {
rates(v)
m' = (minf-m)/mtau
h' = (hinf-h)/htau
n' = (ninf-n)/ntau
}

:LOCAL q10


? rates
PROCEDURE rates(v(mV)) { :Computes rate and other constants at current v.
:Call once from HOC to initialize inf at resting v.
LOCAL alpha, beta, sum, q10
TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200

UNITSOFF
q10 = 3^((celsius - 6.3)/10)
:"m" sodium activation system
alpha = .1 * vtrap(-(v+40),10)
beta = 4 * exp(-(v+65)/18)
sum = alpha + beta
mtau = 1/(q10*sum)
minf = alpha/sum
:"h" sodium inactivation system
alpha = .07 * exp(-(v+65)/20)
beta = 1 / (exp(-(v+35)/10) + 1)
sum = alpha + beta
htau = 1/(q10*sum)
hinf = alpha/sum
:"n" potassium activation system
alpha = .01*vtrap(-(v+55),10)
beta = .125*exp(-(v+65)/80)
sum = alpha + beta
ntau = 1/(q10*sum)
ninf = alpha/sum
}

FUNCTION vtrap(x,y) { :Traps for 0 in denominator of rate eqns.
if (fabs(x/y) < 1e-6) {
vtrap = y*(1 - x/y/2)
}else{
vtrap = x/(exp(x/y) - 1)
}
}

UNITSON
2 changes: 1 addition & 1 deletion src/nrnoc/hh.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ NEURON {
NONSPECIFIC_CURRENT il
RANGE gnabar, gkbar, gl, el, gna, gk
: `GLOBAL minf` will be replaced with `RANGE minf` if CoreNEURON enabled
GLOBAL minf, hinf, ninf, mtau, htau, ntau
RANGE minf, hinf, ninf, mtau, htau, ntau
THREADSAFE : assigned GLOBALs will be per thread
}

Expand Down
6 changes: 1 addition & 5 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ list(APPEND TESTS ringtest)
# Add small hoc test
# =============================================================================
set(HOCTEST_DIR ${PROJECT_SOURCE_DIR}/test/hoc_tests/connect_dend)
if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY)
set(REF_FILE cell3soma.core.dat.ref)
else()
set(REF_FILE cell3soma.dat.ref)
endif()
set(REF_FILE cell3soma.dat.ref)
add_test(
connect_dend
${CMAKE_COMMAND}
Expand Down
84 changes: 84 additions & 0 deletions test/api/hh_sim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// NOTE: this assumes neuronapi.h is on your CPLUS_INCLUDE_PATH
#include "neuronapi.h"
#include <dlfcn.h>

#include <array>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>

#include "./test_common.h"

using std::cout;
using std::endl;
using std::ofstream;

constexpr std::array<double, 3> EXPECTED_V{
-0x1.04p+6,
-0x1.b254ad82e20edp+5,
-0x1.24a52af1ab463p+6,
};

extern "C" void modl_reg(){/* No modl_reg */};

int main(void) {
static std::array<const char*, 4> argv = {"hh_sim", "-nogui", "-nopython", nullptr};
nrn_init(3, argv.data());

// load the stdrun library
char* temp_str = strdup("stdrun.hoc");
nrn_str_push(&temp_str);
nrn_function_call(nrn_symbol("load_file"), 1);
nrn_double_pop();
free(temp_str);

// topology
Section* soma = nrn_section_new("soma");
nrn_nseg_set(soma, 3);

// define soma morphology with two 3d points
nrn_section_push(soma);
for (double x: {0, 0, 0, 10}) {
nrn_double_push(x);
}
nrn_function_call(nrn_symbol("pt3dadd"), 4);
nrn_double_pop(); // pt3dadd returns a number
for (double x: {10, 0, 0, 10}) {
nrn_double_push(x);
}
nrn_function_call(nrn_symbol("pt3dadd"), 4);
nrn_double_pop(); // pt3dadd returns a number

// ion channels
nrn_mechanism_insert(soma, nrn_symbol("hh"));

// current clamp at soma(0.5)
nrn_double_push(0.5);
Object* iclamp = nrn_object_new(nrn_symbol("IClamp"), 1);
nrn_property_set(iclamp, "amp", 0.3);
nrn_property_set(iclamp, "del", 1);
nrn_property_set(iclamp, "dur", 0.1);

// setup recording
Object* v = nrn_object_new(nrn_symbol("Vector"), 0);
nrn_rangevar_push(nrn_symbol("v"), soma, 0.5);
nrn_double_push(5.);
nrn_method_call(v, nrn_method_symbol(v, "record"), 2);
nrn_object_unref(nrn_object_pop()); // record returns the vector

// finitialize(-65)
nrn_double_push(-65);
nrn_function_call(nrn_symbol("finitialize"), 1);
nrn_double_pop();

// continuerun(10)
nrn_double_push(10.5);
nrn_function_call(nrn_symbol("continuerun"), 1);
nrn_double_pop();

if (!approximate(EXPECTED_V, v)) {
return 1;
}
}
94 changes: 94 additions & 0 deletions test/api/netcon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// NOTE: this assumes neuronapi.h is on your CPLUS_INCLUDE_PATH
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include <dlfcn.h>
#include "neuronapi.h"
#include "./test_common.h"

using std::cout;
using std::endl;
using std::ofstream;

constexpr std::array<double, 6> EXPECTED_V{
-0x1.04p+6,
-0x1.085a63d029bc3p+6,
-0x1.112a5e95eb67cp+6,
-0x1.1795abaec26c1p+6,
-0x1.0422351f3f9dcp+6,
-0x1.03e5317ac368cp+6,
};

extern "C" void modl_reg(){/* No modl_reg */};

int main(void) {
static std::array<const char*, 4> argv = {"netcon", "-nogui", "-nopython", nullptr};
nrn_init(3, argv.data());

// load the stdrun library
char* temp_str = strdup("stdrun.hoc");
nrn_str_push(&temp_str);
nrn_function_call(nrn_symbol("load_file"), 1);
nrn_double_pop();
free(temp_str);

// topology
auto soma = nrn_section_new("soma");

// ion channels
nrn_mechanism_insert(soma, nrn_symbol("hh"));

// NetStim
auto ns = nrn_object_new(nrn_symbol("NetStim"), 0);
nrn_property_set(ns, "start", 5);
nrn_property_set(ns, "noise", 1);
nrn_property_set(ns, "interval", 5);
nrn_property_set(ns, "number", 10);

nrn_double_push(1);
nrn_double_push(2);
nrn_double_push(3);
nrn_method_call(ns, nrn_method_symbol(ns, "noiseFromRandom123"), 3);

// syn = h.ExpSyn(soma(0.5))
nrn_double_push(0.5);
auto syn = nrn_object_new(nrn_symbol("ExpSyn"), 1);
nrn_property_set(syn, "tau", 3); // 3 ms timeconstant
nrn_property_set(syn, "e", 0); // 0 mV reversal potential (excitatory synapse)

// nc = h.NetCon(ns, syn)
nrn_object_push(ns);
nrn_object_push(syn);
auto nc = nrn_object_new(nrn_symbol("NetCon"), 2);
nrn_property_array_set(nc, "weight", 0, 0.5);
nrn_property_set(nc, "delay", 0);

auto vec = nrn_object_new(nrn_symbol("Vector"), 0);

// nc.record(vec)
nrn_object_push(vec);
nrn_method_call(nc, nrn_method_symbol(nc, "record"), 1);
// TODO: record probably put something on the stack that should be removed

// setup recording
Object* v = nrn_object_new(nrn_symbol("Vector"), 0);
nrn_rangevar_push(nrn_symbol("v"), soma, 0.5);
nrn_double_push(20);
nrn_method_call(v, nrn_method_symbol(v, "record"), 2);
nrn_object_unref(nrn_object_pop()); // record returns the vector

// finitialize(-65)
nrn_double_push(-65);
nrn_function_call(nrn_symbol("finitialize"), 1);
nrn_double_pop();

// continuerun(100)
nrn_double_push(100.5);
nrn_function_call(nrn_symbol("continuerun"), 1);
nrn_double_pop();

if (!approximate(EXPECTED_V, v)) {
return 1;
}
}
4 changes: 2 additions & 2 deletions test/external/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ include(FetchContent)
FetchContent_Declare(
ringtest
GIT_REPOSITORY https://github.com/neuronsimulator/ringtest
GIT_TAG ee24c8
GIT_TAG 7d1aee72939f6dfcb2a14db4c7b00725d9e485fa
SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/ringtest)

FetchContent_Declare(
testcorenrn
GIT_REPOSITORY https://github.com/neuronsimulator/testcorenrn
GIT_TAG 41a6d7ea47551559cc89a71544a746a5d3c2a6b8
GIT_TAG e53831b3963af8be412e16807a85157e4413f307
SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/testcorenrn)

FetchContent_Declare(
Expand Down
Loading

0 comments on commit 16ab91d

Please sign in to comment.