From e8c05cfb3fbff28f4216dda736aafa63876d144c Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Tue, 8 Oct 2024 10:06:07 +0000 Subject: [PATCH] References for 'https://github.com/BlueBrain/nmodl/pull/1364'. --- at_time/neuron/example.cpp | 10 +- builtin_functions/neuron/compile_only.cpp | 10 +- constant/neuron/constant.cpp | 10 +- constructor/neuron/art_ctor.cpp | 13 +- constructor/neuron/ctor.cpp | 11 +- electrode_current/neuron/leonhard.cpp | 18 +- external/neuron/dst.cpp | 10 +- external/neuron/src.cpp | 10 +- function/neuron/artificial_functions.cpp | 12 +- function/neuron/compile_only.cpp | 18 +- function/neuron/functions.cpp | 10 +- function/neuron/localize_arguments.cpp | 10 +- function/neuron/non_threadsafe.cpp | 10 +- function/neuron/point_functions.cpp | 10 +- function/neuron/point_non_threadsafe.cpp | 10 +- function/neuron/recursion.cpp | 10 +- function_table/neuron/function_table.cpp | 10 +- global/neuron/non_threadsafe.cpp | 10 +- global/neuron/read_only.cpp | 14 +- global/neuron/thread_newton.cpp | 15 +- global/neuron/thread_variable.cpp | 19 +- global/neuron/top_local.cpp | 19 +- hodgkin_huxley/neuron/hodhux.cpp | 18 +- kinetic/neuron/X2Y.cpp | 18 +- kinetic/neuron/side_effects.cpp | 18 +- linear/neuron/lin.cpp | 10 +- .../coreneuron/heat_eqn_array.cpp | 773 +++++++++++++++ .../coreneuron/heat_eqn_function.cpp | 5 + .../coreneuron/heat_eqn_global.cpp | 725 ++++++++++++++ .../coreneuron/heat_eqn_scalar.cpp | 727 ++++++++++++++ .../coreneuron/heat_eqn_thread_vars.cpp | 5 + .../neuron/heat_eqn_array.cpp | 794 +++++++++++++++ .../neuron/heat_eqn_function.cpp | 938 ++++++++++++++++++ .../neuron/heat_eqn_global.cpp | 742 ++++++++++++++ .../neuron/heat_eqn_scalar.cpp | 740 ++++++++++++++ .../neuron/heat_eqn_thread_vars.cpp | 796 +++++++++++++++ morphology/neuron/two_radii.cpp | 18 +- net_event/neuron/receiver.cpp | 10 +- net_event/neuron/spiker.cpp | 10 +- net_move/neuron/art_spiker.cpp | 12 +- net_move/neuron/spiker.cpp | 10 +- net_receive/neuron/NetReceiveCalls.cpp | 10 +- net_receive/neuron/for_netcons_syn.cpp | 10 +- net_receive/neuron/initsyn.cpp | 10 +- net_receive/neuron/snapsyn.cpp | 18 +- net_send/neuron/art_toggle.cpp | 12 +- net_send/neuron/toggle.cpp | 10 +- neuron_variables/neuron/neuron_variables.cpp | 14 +- nonspecific_current/neuron/leonhard.cpp | 18 +- parameter/neuron/default_parameter.cpp | 10 +- parameter/neuron/limits.cpp | 10 +- parameter/neuron/range_parameter.cpp | 10 +- point_process/neuron/pp.cpp | 10 +- pointer/neuron/basic_pointer.cpp | 10 +- pointer/neuron/point_basic.cpp | 10 +- pointer/neuron/pointing.cpp | 10 +- procedure/neuron/point_procedures.cpp | 10 +- procedure/neuron/procedures.cpp | 10 +- random/neuron/random_variable.cpp | 10 +- solve/neuron/cnexp_array.cpp | 14 +- solve/neuron/cnexp_scalar.cpp | 14 +- solve/neuron/derivimplicit_array.cpp | 14 +- solve/neuron/derivimplicit_scalar.cpp | 14 +- solve/neuron/finite_difference.cpp | 15 +- spike_travel/neuron/expsyn2.cpp | 18 +- spike_travel/neuron/hodhux.cpp | 18 +- state/neuron/default_values.cpp | 10 +- steady_state/neuron/minipump.cpp | 14 +- suffix/neuron/no_suffix.cpp | 10 +- suffix/neuron/point_suffix.cpp | 10 +- table/neuron/table.cpp | 18 +- table/neuron/table_point_process.cpp | 18 +- useion/neuron/ionic.cpp | 14 +- useion/neuron/read_cai.cpp | 10 +- useion/neuron/read_cao.cpp | 10 +- useion/neuron/read_eca.cpp | 10 +- useion/neuron/style_ion.cpp | 10 +- useion/neuron/valence.cpp | 10 +- useion/neuron/write_cai.cpp | 10 +- useion/neuron/write_cao.cpp | 10 +- useion/neuron/write_eca.cpp | 10 +- verbatim/neuron/globals.cpp | 10 +- verbatim/neuron/internal_function.cpp | 10 +- verbatim/neuron/pointer_in_double.cpp | 10 +- 84 files changed, 6845 insertions(+), 306 deletions(-) create mode 100644 longitudinal_diffusion/coreneuron/heat_eqn_array.cpp create mode 100644 longitudinal_diffusion/coreneuron/heat_eqn_function.cpp create mode 100644 longitudinal_diffusion/coreneuron/heat_eqn_global.cpp create mode 100644 longitudinal_diffusion/coreneuron/heat_eqn_scalar.cpp create mode 100644 longitudinal_diffusion/coreneuron/heat_eqn_thread_vars.cpp create mode 100644 longitudinal_diffusion/neuron/heat_eqn_array.cpp create mode 100644 longitudinal_diffusion/neuron/heat_eqn_function.cpp create mode 100644 longitudinal_diffusion/neuron/heat_eqn_global.cpp create mode 100644 longitudinal_diffusion/neuron/heat_eqn_scalar.cpp create mode 100644 longitudinal_diffusion/neuron/heat_eqn_thread_vars.cpp diff --git a/at_time/neuron/example.cpp b/at_time/neuron/example.cpp index f566891a..e45b17f7 100644 --- a/at_time/neuron/example.cpp +++ b/at_time/neuron/example.cpp @@ -144,6 +144,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double f_example(_nrn_mechanism_cache_range& _lmc, example_Instance& inst, example_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -226,11 +229,11 @@ namespace neuron { void nrn_init_example(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_example(_lmc); auto node_data = make_node_data_example(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -240,9 +243,10 @@ namespace neuron { static void nrn_jacob_example(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_example(_lmc); auto node_data = make_node_data_example(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/builtin_functions/neuron/compile_only.cpp b/builtin_functions/neuron/compile_only.cpp index 1f22064b..630a207f 100644 --- a/builtin_functions/neuron/compile_only.cpp +++ b/builtin_functions/neuron/compile_only.cpp @@ -144,6 +144,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double call_nrn_ghk_compile_only(_nrn_mechanism_cache_range& _lmc, compile_only_Instance& inst, compile_only_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -226,11 +229,11 @@ namespace neuron { void nrn_init_compile_only(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_compile_only(_lmc); auto node_data = make_node_data_compile_only(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -240,9 +243,10 @@ namespace neuron { static void nrn_jacob_compile_only(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_compile_only(_lmc); auto node_data = make_node_data_compile_only(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/constant/neuron/constant.cpp b/constant/neuron/constant.cpp index e14cf123..a694b9a2 100644 --- a/constant/neuron/constant.cpp +++ b/constant/neuron/constant.cpp @@ -149,6 +149,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double foo_constant_mod(_nrn_mechanism_cache_range& _lmc, constant_mod_Instance& inst, constant_mod_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -231,11 +234,11 @@ namespace neuron { void nrn_init_constant_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_constant_mod(_lmc); auto node_data = make_node_data_constant_mod(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -245,9 +248,10 @@ namespace neuron { static void nrn_jacob_constant_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_constant_mod(_lmc); auto node_data = make_node_data_constant_mod(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/constructor/neuron/art_ctor.cpp b/constructor/neuron/art_ctor.cpp index 55848304..21b8eb60 100644 --- a/constructor/neuron/art_ctor.cpp +++ b/constructor/neuron/art_ctor.cpp @@ -187,6 +187,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -262,12 +265,11 @@ namespace neuron { void nrn_init_art_ctor(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_ctor(_lmc); - auto node_data = make_node_data_art_ctor(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = art_ctor_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; } @@ -275,9 +277,10 @@ namespace neuron { static void nrn_jacob_art_ctor(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_ctor(_lmc); - auto node_data = make_node_data_art_ctor(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = art_ctor_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/constructor/neuron/ctor.cpp b/constructor/neuron/ctor.cpp index 59436fc9..c4f42129 100644 --- a/constructor/neuron/ctor.cpp +++ b/constructor/neuron/ctor.cpp @@ -187,6 +187,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -262,12 +265,12 @@ namespace neuron { void nrn_init_ctor(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ctor(_lmc); auto node_data = make_node_data_ctor(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = ctor_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -277,9 +280,11 @@ namespace neuron { static void nrn_jacob_ctor(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ctor(_lmc); auto node_data = make_node_data_ctor(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = ctor_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/electrode_current/neuron/leonhard.cpp b/electrode_current/neuron/leonhard.cpp index d443930f..f77a583b 100644 --- a/electrode_current/neuron/leonhard.cpp +++ b/electrode_current/neuron/leonhard.cpp @@ -152,6 +152,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -191,11 +194,11 @@ namespace neuron { void nrn_init_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -214,11 +217,11 @@ namespace neuron { /** update current */ void nrn_cur_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -234,11 +237,11 @@ namespace neuron { void nrn_state_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -248,9 +251,10 @@ namespace neuron { static void nrn_jacob_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/external/neuron/dst.cpp b/external/neuron/dst.cpp index ddee55c8..a7283a87 100644 --- a/external/neuron/dst.cpp +++ b/external/neuron/dst.cpp @@ -148,6 +148,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double get_gbl_dst(_nrn_mechanism_cache_range& _lmc, dst_Instance& inst, dst_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double get_param_dst(_nrn_mechanism_cache_range& _lmc, dst_Instance& inst, dst_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -273,11 +276,11 @@ namespace neuron { void nrn_init_dst(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_dst(_lmc); auto node_data = make_node_data_dst(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -287,9 +290,10 @@ namespace neuron { static void nrn_jacob_dst(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_dst(_lmc); auto node_data = make_node_data_dst(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/external/neuron/src.cpp b/external/neuron/src.cpp index 29035046..b543bf4d 100644 --- a/external/neuron/src.cpp +++ b/external/neuron/src.cpp @@ -152,6 +152,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -193,11 +196,11 @@ namespace neuron { void nrn_init_src(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_src(_lmc); auto node_data = make_node_data_src(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -207,9 +210,10 @@ namespace neuron { static void nrn_jacob_src(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_src(_lmc); auto node_data = make_node_data_src(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/artificial_functions.cpp b/function/neuron/artificial_functions.cpp index ab7b229d..320e4063 100644 --- a/function/neuron/artificial_functions.cpp +++ b/function/neuron/artificial_functions.cpp @@ -170,6 +170,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double x_plus_a_art_functions(_nrn_mechanism_cache_range& _lmc, art_functions_Instance& inst, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double identity_art_functions(_nrn_mechanism_cache_range& _lmc, art_functions_Instance& inst, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -282,11 +285,10 @@ namespace neuron { void nrn_init_art_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_functions(_lmc); - auto node_data = make_node_data_art_functions(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; inst.z[id] = inst.global->z0; @@ -297,9 +299,9 @@ namespace neuron { static void nrn_jacob_art_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_functions(_lmc); - auto node_data = make_node_data_art_functions(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/compile_only.cpp b/function/neuron/compile_only.cpp index 9b11beda..c444937c 100644 --- a/function/neuron/compile_only.cpp +++ b/function/neuron/compile_only.cpp @@ -156,6 +156,9 @@ namespace neuron { inline int func_func_in_breakpoint(_nrn_mechanism_cache_range& _lmc, func_in_breakpoint_Instance& inst, func_in_breakpoint_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int func_with_v_func_in_breakpoint(_nrn_mechanism_cache_range& _lmc, func_in_breakpoint_Instance& inst, func_in_breakpoint_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); inline int func_with_other_func_in_breakpoint(_nrn_mechanism_cache_range& _lmc, func_in_breakpoint_Instance& inst, func_in_breakpoint_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lq); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -328,11 +331,11 @@ namespace neuron { void nrn_init_func_in_breakpoint(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_func_in_breakpoint(_lmc); auto node_data = make_node_data_func_in_breakpoint(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -353,11 +356,11 @@ namespace neuron { /** update current */ void nrn_cur_func_in_breakpoint(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_func_in_breakpoint(_lmc); auto node_data = make_node_data_func_in_breakpoint(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -373,11 +376,11 @@ namespace neuron { void nrn_state_func_in_breakpoint(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_func_in_breakpoint(_lmc); auto node_data = make_node_data_func_in_breakpoint(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -387,9 +390,10 @@ namespace neuron { static void nrn_jacob_func_in_breakpoint(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_func_in_breakpoint(_lmc); auto node_data = make_node_data_func_in_breakpoint(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/function/neuron/functions.cpp b/function/neuron/functions.cpp index 28bf812b..a4e805a5 100644 --- a/function/neuron/functions.cpp +++ b/function/neuron/functions.cpp @@ -149,6 +149,9 @@ namespace neuron { inline double x_plus_a_functions(_nrn_mechanism_cache_range& _lmc, functions_Instance& inst, functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double v_plus_a_functions(_nrn_mechanism_cache_range& _lmc, functions_Instance& inst, functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double identity_functions(_nrn_mechanism_cache_range& _lmc, functions_Instance& inst, functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -320,11 +323,11 @@ namespace neuron { void nrn_init_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_functions(_lmc); auto node_data = make_node_data_functions(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -335,9 +338,10 @@ namespace neuron { static void nrn_jacob_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_functions(_lmc); auto node_data = make_node_data_functions(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/localize_arguments.cpp b/function/neuron/localize_arguments.cpp index 6902237e..e701e5ff 100644 --- a/function/neuron/localize_arguments.cpp +++ b/function/neuron/localize_arguments.cpp @@ -191,6 +191,9 @@ namespace neuron { inline double id_g_localize_arguments(_nrn_mechanism_cache_range& _lmc, localize_arguments_Instance& inst, localize_arguments_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lg); inline double id_s_localize_arguments(_nrn_mechanism_cache_range& _lmc, localize_arguments_Instance& inst, localize_arguments_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _ls); inline double id_p_localize_arguments(_nrn_mechanism_cache_range& _lmc, localize_arguments_Instance& inst, localize_arguments_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lp); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -533,11 +536,11 @@ namespace neuron { void nrn_init_localize_arguments(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_localize_arguments(_lmc); auto node_data = make_node_data_localize_arguments(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -552,9 +555,10 @@ namespace neuron { static void nrn_jacob_localize_arguments(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_localize_arguments(_lmc); auto node_data = make_node_data_localize_arguments(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/non_threadsafe.cpp b/function/neuron/non_threadsafe.cpp index 121617d6..9de6899e 100644 --- a/function/neuron/non_threadsafe.cpp +++ b/function/neuron/non_threadsafe.cpp @@ -161,6 +161,9 @@ namespace neuron { inline double x_plus_a_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double v_plus_a_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double identity_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -333,11 +336,11 @@ namespace neuron { void nrn_init_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_non_threadsafe(_lmc); auto node_data = make_node_data_non_threadsafe(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -350,9 +353,10 @@ namespace neuron { static void nrn_jacob_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_non_threadsafe(_lmc); auto node_data = make_node_data_non_threadsafe(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/point_functions.cpp b/function/neuron/point_functions.cpp index 576df670..cfbec74e 100644 --- a/function/neuron/point_functions.cpp +++ b/function/neuron/point_functions.cpp @@ -159,6 +159,9 @@ namespace neuron { inline double x_plus_a_point_functions(_nrn_mechanism_cache_range& _lmc, point_functions_Instance& inst, point_functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double v_plus_a_point_functions(_nrn_mechanism_cache_range& _lmc, point_functions_Instance& inst, point_functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double identity_point_functions(_nrn_mechanism_cache_range& _lmc, point_functions_Instance& inst, point_functions_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -304,11 +307,11 @@ namespace neuron { void nrn_init_point_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_functions(_lmc); auto node_data = make_node_data_point_functions(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -319,9 +322,10 @@ namespace neuron { static void nrn_jacob_point_functions(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_functions(_lmc); auto node_data = make_node_data_point_functions(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/point_non_threadsafe.cpp b/function/neuron/point_non_threadsafe.cpp index 49491858..1810e906 100644 --- a/function/neuron/point_non_threadsafe.cpp +++ b/function/neuron/point_non_threadsafe.cpp @@ -171,6 +171,9 @@ namespace neuron { inline double x_plus_a_point_non_threadsafe(_nrn_mechanism_cache_range& _lmc, point_non_threadsafe_Instance& inst, point_non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double v_plus_a_point_non_threadsafe(_nrn_mechanism_cache_range& _lmc, point_non_threadsafe_Instance& inst, point_non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _la); inline double identity_point_non_threadsafe(_nrn_mechanism_cache_range& _lmc, point_non_threadsafe_Instance& inst, point_non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -317,11 +320,11 @@ namespace neuron { void nrn_init_point_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_non_threadsafe(_lmc); auto node_data = make_node_data_point_non_threadsafe(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -334,9 +337,10 @@ namespace neuron { static void nrn_jacob_point_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_non_threadsafe(_lmc); auto node_data = make_node_data_point_non_threadsafe(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function/neuron/recursion.cpp b/function/neuron/recursion.cpp index 24118feb..4b6517b3 100644 --- a/function/neuron/recursion.cpp +++ b/function/neuron/recursion.cpp @@ -144,6 +144,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double fibonacci_recursion(_nrn_mechanism_cache_range& _lmc, recursion_Instance& inst, recursion_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _ln); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -230,11 +233,11 @@ namespace neuron { void nrn_init_recursion(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_recursion(_lmc); auto node_data = make_node_data_recursion(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -244,9 +247,10 @@ namespace neuron { static void nrn_jacob_recursion(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_recursion(_lmc); auto node_data = make_node_data_recursion(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/function_table/neuron/function_table.cpp b/function_table/neuron/function_table.cpp index 8fb5a35c..0cc7eed3 100644 --- a/function_table/neuron/function_table.cpp +++ b/function_table/neuron/function_table.cpp @@ -169,6 +169,9 @@ namespace neuron { double table_tau1_function_table(); double tau2_function_table(double v, double x); double table_tau2_function_table(); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -361,11 +364,11 @@ namespace neuron { void nrn_init_function_table(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_function_table(_lmc); auto node_data = make_node_data_function_table(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -375,9 +378,10 @@ namespace neuron { static void nrn_jacob_function_table(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_function_table(_lmc); auto node_data = make_node_data_function_table(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/global/neuron/non_threadsafe.cpp b/global/neuron/non_threadsafe.cpp index ac115801..21d2516d 100644 --- a/global/neuron/non_threadsafe.cpp +++ b/global/neuron/non_threadsafe.cpp @@ -166,6 +166,9 @@ namespace neuron { inline double get_gbl_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double get_top_local_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double get_parameter_non_threadsafe(_nrn_mechanism_cache_range& _lmc, non_threadsafe_Instance& inst, non_threadsafe_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -336,11 +339,11 @@ namespace neuron { void nrn_init_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_non_threadsafe(_lmc); auto node_data = make_node_data_non_threadsafe(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -353,9 +356,10 @@ namespace neuron { static void nrn_jacob_non_threadsafe(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_non_threadsafe(_lmc); auto node_data = make_node_data_non_threadsafe(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/global/neuron/read_only.cpp b/global/neuron/read_only.cpp index fe87ee88..379ffe26 100644 --- a/global/neuron/read_only.cpp +++ b/global/neuron/read_only.cpp @@ -159,6 +159,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -199,11 +202,11 @@ namespace neuron { void nrn_init_read_only(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_only(_lmc); auto node_data = make_node_data_read_only(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -215,11 +218,11 @@ namespace neuron { void nrn_state_read_only(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_only(_lmc); auto node_data = make_node_data_read_only(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -230,9 +233,10 @@ namespace neuron { static void nrn_jacob_read_only(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_only(_lmc); auto node_data = make_node_data_read_only(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/global/neuron/thread_newton.cpp b/global/neuron/thread_newton.cpp index fee1527e..b333b277 100644 --- a/global/neuron/thread_newton.cpp +++ b/global/neuron/thread_newton.cpp @@ -568,6 +568,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -661,12 +664,12 @@ namespace neuron { void nrn_init_thread_newton(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_thread_newton(_lmc); auto node_data = make_node_data_thread_newton(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = thread_newton_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -680,12 +683,12 @@ namespace neuron { void nrn_state_thread_newton(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_thread_newton(_lmc); auto node_data = make_node_data_thread_newton(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = thread_newton_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -709,9 +712,11 @@ namespace neuron { static void nrn_jacob_thread_newton(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_thread_newton(_lmc); auto node_data = make_node_data_thread_newton(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = thread_newton_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/global/neuron/thread_variable.cpp b/global/neuron/thread_variable.cpp index 8f01c6a6..6437c434 100644 --- a/global/neuron/thread_variable.cpp +++ b/global/neuron/thread_variable.cpp @@ -212,6 +212,9 @@ namespace neuron { inline double sum_arr_shared_global(_nrn_mechanism_cache_range& _lmc, shared_global_Instance& inst, shared_global_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, shared_global_ThreadVariables& _thread_vars, NrnThread* nt); inline int set_g_w_shared_global(_nrn_mechanism_cache_range& _lmc, shared_global_Instance& inst, shared_global_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, shared_global_ThreadVariables& _thread_vars, NrnThread* nt, double _lzz); inline int compute_g_v1_shared_global(_nrn_mechanism_cache_range& _lmc, shared_global_Instance& inst, shared_global_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, shared_global_ThreadVariables& _thread_vars, NrnThread* nt, double _lzz); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -465,12 +468,12 @@ namespace neuron { void nrn_init_shared_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_shared_global(_lmc); auto node_data = make_node_data_shared_global(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = shared_global_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -503,12 +506,12 @@ namespace neuron { /** update current */ void nrn_cur_shared_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_shared_global(_lmc); auto node_data = make_node_data_shared_global(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = shared_global_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -524,12 +527,12 @@ namespace neuron { void nrn_state_shared_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_shared_global(_lmc); auto node_data = make_node_data_shared_global(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = shared_global_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -539,9 +542,11 @@ namespace neuron { static void nrn_jacob_shared_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_shared_global(_lmc); auto node_data = make_node_data_shared_global(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = shared_global_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/global/neuron/top_local.cpp b/global/neuron/top_local.cpp index 1e4e492c..91788ee4 100644 --- a/global/neuron/top_local.cpp +++ b/global/neuron/top_local.cpp @@ -177,6 +177,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -234,12 +237,12 @@ namespace neuron { void nrn_init_top_local(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_top_local(_lmc); auto node_data = make_node_data_top_local(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = top_local_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -263,12 +266,12 @@ namespace neuron { /** update current */ void nrn_cur_top_local(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_top_local(_lmc); auto node_data = make_node_data_top_local(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = top_local_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -284,12 +287,12 @@ namespace neuron { void nrn_state_top_local(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_top_local(_lmc); auto node_data = make_node_data_top_local(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = top_local_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -299,9 +302,11 @@ namespace neuron { static void nrn_jacob_top_local(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_top_local(_lmc); auto node_data = make_node_data_top_local(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = top_local_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/hodgkin_huxley/neuron/hodhux.cpp b/hodgkin_huxley/neuron/hodhux.cpp index 432cbbca..b35363b2 100644 --- a/hodgkin_huxley/neuron/hodhux.cpp +++ b/hodgkin_huxley/neuron/hodhux.cpp @@ -257,6 +257,9 @@ namespace neuron { inline double vtrap_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx, double _ly); inline int states_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int rates_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -459,11 +462,11 @@ namespace neuron { void nrn_init_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -495,11 +498,11 @@ namespace neuron { /** update current */ void nrn_cur_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -523,11 +526,11 @@ namespace neuron { void nrn_state_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -543,9 +546,10 @@ namespace neuron { static void nrn_jacob_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/kinetic/neuron/X2Y.cpp b/kinetic/neuron/X2Y.cpp index 716bf12c..9adbd8f1 100644 --- a/kinetic/neuron/X2Y.cpp +++ b/kinetic/neuron/X2Y.cpp @@ -561,6 +561,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline int rates_X2Y(_nrn_mechanism_cache_range& _lmc, X2Y_Instance& inst, X2Y_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -692,11 +695,11 @@ namespace neuron { void nrn_init_X2Y(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_X2Y(_lmc); auto node_data = make_node_data_X2Y(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -721,11 +724,11 @@ namespace neuron { /** update current */ void nrn_cur_X2Y(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_X2Y(_lmc); auto node_data = make_node_data_X2Y(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -741,11 +744,11 @@ namespace neuron { void nrn_state_X2Y(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_X2Y(_lmc); auto node_data = make_node_data_X2Y(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -770,9 +773,10 @@ namespace neuron { static void nrn_jacob_X2Y(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_X2Y(_lmc); auto node_data = make_node_data_X2Y(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/kinetic/neuron/side_effects.cpp b/kinetic/neuron/side_effects.cpp index e4d0f5a6..19256029 100644 --- a/kinetic/neuron/side_effects.cpp +++ b/kinetic/neuron/side_effects.cpp @@ -561,6 +561,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -644,11 +647,11 @@ namespace neuron { void nrn_init_side_effects(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_side_effects(_lmc); auto node_data = make_node_data_side_effects(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -671,11 +674,11 @@ namespace neuron { /** update current */ void nrn_cur_side_effects(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_side_effects(_lmc); auto node_data = make_node_data_side_effects(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -691,11 +694,11 @@ namespace neuron { void nrn_state_side_effects(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_side_effects(_lmc); auto node_data = make_node_data_side_effects(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -720,9 +723,10 @@ namespace neuron { static void nrn_jacob_side_effects(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_side_effects(_lmc); auto node_data = make_node_data_side_effects(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/linear/neuron/lin.cpp b/linear/neuron/lin.cpp index 73a49f9c..ccdfbeda 100644 --- a/linear/neuron/lin.cpp +++ b/linear/neuron/lin.cpp @@ -176,6 +176,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -219,11 +222,11 @@ namespace neuron { void nrn_init_lin(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_lin(_lmc); auto node_data = make_node_data_lin(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -238,9 +241,10 @@ namespace neuron { static void nrn_jacob_lin(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_lin(_lmc); auto node_data = make_node_data_lin(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/longitudinal_diffusion/coreneuron/heat_eqn_array.cpp b/longitudinal_diffusion/coreneuron/heat_eqn_array.cpp new file mode 100644 index 00000000..6384e168 --- /dev/null +++ b/longitudinal_diffusion/coreneuron/heat_eqn_array.cpp @@ -0,0 +1,773 @@ +/********************************************************* +Model Name : heat_eqn_array +Filename : heat_eqn_array.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : CoreNEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + + +namespace coreneuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_array", + 0, + "x_heat_eqn_array", + 0, + "X_heat_eqn_array[4]", + 0, + 0 + }; + + + /** all global variables */ + struct heat_eqn_array_Store { + double X0{}; + int reset{}; + int mech_type{}; + double kf{0}; + double kb{0}; + int slist1[4]{1}; + int dlist1[4]{13}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_array_Store heat_eqn_array_global; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_array_Instance { + double* x{}; + double* X{}; + double* mu{}; + double* vol{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_array_Store* global{&heat_eqn_array_global}; + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"kf_heat_eqn_array", &heat_eqn_array_global.kf}, + {"kb_heat_eqn_array", &heat_eqn_array_global.kb}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + static inline int first_pointer_var_index() { + return -1; + } + + + static inline int first_random_var_index() { + return -1; + } + + + static inline int float_variables_size() { + return 19; + } + + + static inline int int_variables_size() { + return 0; + } + + + static inline int get_mech_type() { + return heat_eqn_array_global.mech_type; + } + + + static inline Memb_list* get_memb_list(NrnThread* nt) { + if (!nt->_ml_list) { + return nullptr; + } + return nt->_ml_list[get_mech_type()]; + } + + + static inline void* mem_alloc(size_t num, size_t size, size_t alignment = 64) { + size_t aligned_size = ((num*size + alignment - 1) / alignment) * alignment; + void* ptr = aligned_alloc(alignment, aligned_size); + memset(ptr, 0, aligned_size); + return ptr; + } + + + static inline void mem_free(void* ptr) { + free(ptr); + } + + + static inline void coreneuron_abort() { + abort(); + } + + // Allocate instance structure + static void nrn_private_constructor_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + assert(!ml->instance); + assert(!ml->global_variables); + assert(ml->global_variables_size == 0); + auto* const inst = new heat_eqn_array_Instance{}; + assert(inst->global == &heat_eqn_array_global); + ml->instance = inst; + ml->global_variables = inst->global; + ml->global_variables_size = sizeof(heat_eqn_array_Store); + } + + // Deallocate the instance structure + static void nrn_private_destructor_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_array_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_array_Store)); + delete inst; + ml->instance = nullptr; + ml->global_variables = nullptr; + ml->global_variables_size = 0; + } + + /** initialize mechanism instance variables */ + static inline void setup_instance(NrnThread* nt, Memb_list* ml) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_array_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_array_Store)); + int pnodecount = ml->_nodecount_padded; + Datum* indexes = ml->pdata; + inst->x = ml->data+0*pnodecount; + inst->X = ml->data+1*pnodecount; + inst->mu = ml->data+5*pnodecount; + inst->vol = ml->data+9*pnodecount; + inst->DX = ml->data+13*pnodecount; + inst->v_unused = ml->data+17*pnodecount; + inst->g_unused = ml->data+18*pnodecount; + } + + + + static void nrn_alloc_heat_eqn_array(double* data, Datum* indexes, int type) { + // do nothing + } + + + void nrn_constructor_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + void nrn_destructor_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + struct functor_heat_eqn_array_0 { + NrnThread* nt; + heat_eqn_array_Instance* inst; + int id; + int pnodecount; + double v; + const Datum* indexes; + double* data; + ThreadDatum* thread; + double kf0_, kb0_, kf1_, kb1_, kf2_, kb2_, old_X_0, old_X_1, old_X_2, old_X_3; + + void initialize() { + i(inst->mu+id*4)[static_cast(i)](inst->X+id*4); + { + kf0_ = inst->global->kf; + kb0_ = inst->global->kb; + kf1_ = inst->global->kf; + kb1_ = inst->global->kb; + kf2_ = inst->global->kf; + kb2_ = inst->global->kb; + } + old_X_0 = (inst->X+id*4)[static_cast(0)]; + old_X_1 = (inst->X+id*4)[static_cast(1)]; + old_X_2 = (inst->X+id*4)[static_cast(2)]; + old_X_3 = (inst->X+id*4)[static_cast(3)]; + } + + functor_heat_eqn_array_0(NrnThread* nt, heat_eqn_array_Instance* inst, int id, int pnodecount, double v, const Datum* indexes, double* data, ThreadDatum* thread) + : nt(nt), inst(inst), id(id), pnodecount(pnodecount), v(v), indexes(indexes), data(data), thread(thread) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_dx[1] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[1])); + nmodl_eigen_dx[2] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[2])); + nmodl_eigen_dx[3] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[3])); + nmodl_eigen_f[static_cast(0)] = (nt->_dt * ( -nmodl_eigen_x[static_cast(0)] * kf0_ + nmodl_eigen_x[static_cast(1)] * kb0_) + ( -nmodl_eigen_x[static_cast(0)] + old_X_0) * (inst->vol+id*4)[static_cast(0)]) / (nt->_dt * (inst->vol+id*4)[static_cast(0)]); + nmodl_eigen_j[static_cast(0)] = -kf0_ / (inst->vol+id*4)[static_cast(0)] - 1.0 / nt->_dt; + nmodl_eigen_j[static_cast(4)] = kb0_ / (inst->vol+id*4)[static_cast(0)]; + nmodl_eigen_j[static_cast(8)] = 0.0; + nmodl_eigen_j[static_cast(12)] = 0.0; + nmodl_eigen_f[static_cast(1)] = (nt->_dt * (nmodl_eigen_x[static_cast(0)] * kf0_ - nmodl_eigen_x[static_cast(1)] * kb0_ - nmodl_eigen_x[static_cast(1)] * kf1_ + nmodl_eigen_x[static_cast(2)] * kb1_) + ( -nmodl_eigen_x[static_cast(1)] + old_X_1) * (inst->vol+id*4)[static_cast(1)]) / (nt->_dt * (inst->vol+id*4)[static_cast(1)]); + nmodl_eigen_j[static_cast(1)] = kf0_ / (inst->vol+id*4)[static_cast(1)]; + nmodl_eigen_j[static_cast(5)] = (nt->_dt * ( -kb0_ - kf1_) - (inst->vol+id*4)[static_cast(1)]) / (nt->_dt * (inst->vol+id*4)[static_cast(1)]); + nmodl_eigen_j[static_cast(9)] = kb1_ / (inst->vol+id*4)[static_cast(1)]; + nmodl_eigen_j[static_cast(13)] = 0.0; + nmodl_eigen_f[static_cast(2)] = (nt->_dt * (nmodl_eigen_x[static_cast(1)] * kf1_ - nmodl_eigen_x[static_cast(2)] * kb1_ - nmodl_eigen_x[static_cast(2)] * kf2_ + nmodl_eigen_x[static_cast(3)] * kb2_) + ( -nmodl_eigen_x[static_cast(2)] + old_X_2) * (inst->vol+id*4)[static_cast(2)]) / (nt->_dt * (inst->vol+id*4)[static_cast(2)]); + nmodl_eigen_j[static_cast(2)] = 0.0; + nmodl_eigen_j[static_cast(6)] = kf1_ / (inst->vol+id*4)[static_cast(2)]; + nmodl_eigen_j[static_cast(10)] = (nt->_dt * ( -kb1_ - kf2_) - (inst->vol+id*4)[static_cast(2)]) / (nt->_dt * (inst->vol+id*4)[static_cast(2)]); + nmodl_eigen_j[static_cast(14)] = kb2_ / (inst->vol+id*4)[static_cast(2)]; + nmodl_eigen_f[static_cast(3)] = (nt->_dt * (nmodl_eigen_x[static_cast(2)] * kf2_ - nmodl_eigen_x[static_cast(3)] * kb2_) + ( -nmodl_eigen_x[static_cast(3)] + old_X_3) * (inst->vol+id*4)[static_cast(3)]) / (nt->_dt * (inst->vol+id*4)[static_cast(3)]); + nmodl_eigen_j[static_cast(3)] = 0.0; + nmodl_eigen_j[static_cast(7)] = 0.0; + nmodl_eigen_j[static_cast(11)] = kf2_ / (inst->vol+id*4)[static_cast(3)]; + nmodl_eigen_j[static_cast(15)] = -kb2_ / (inst->vol+id*4)[static_cast(3)] - 1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** initialize channel */ + void nrn_init_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + + setup_instance(nt, ml); + auto* const inst = static_cast(ml->instance); + + if (_nrn_skip_initmodel == 0) { + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + (inst->X+id*4)[0] = inst->global->X0; + (inst->X+id*4)[1] = inst->global->X0; + (inst->X+id*4)[2] = inst->global->X0; + (inst->X+id*4)[3] = inst->global->X0; + for (int i = 0; i <= 4 - 1; i++) { + (inst->mu+id*4)[static_cast(i)] = 1.0 + i; + (inst->vol+id*4)[static_cast(i)] = 0.01 / (i + 1.0); + if (inst->x[id] < 0.5) { + (inst->X+id*4)[static_cast(i)] = 1.0 + i; + } else { + (inst->X+id*4)[static_cast(i)] = 0.0; + } + } + } + } + } + + + /** update state */ + void nrn_state_heat_eqn_array(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = (inst->X+id*4)[static_cast(0)]; + nmodl_eigen_x[static_cast(1)] = (inst->X+id*4)[static_cast(1)]; + nmodl_eigen_x[static_cast(2)] = (inst->X+id*4)[static_cast(2)]; + nmodl_eigen_x[static_cast(3)] = (inst->X+id*4)[static_cast(3)]; + // call newton solver + functor_heat_eqn_array_0 newton_functor(nt, inst, id, pnodecount, v, indexes, data, thread); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + (inst->X+id*4)[static_cast(0)] = nmodl_eigen_x[static_cast(0)]; + (inst->X+id*4)[static_cast(1)] = nmodl_eigen_x[static_cast(1)]; + (inst->X+id*4)[static_cast(2)] = nmodl_eigen_x[static_cast(2)]; + (inst->X+id*4)[static_cast(3)] = nmodl_eigen_x[static_cast(3)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + /** register channel with the simulator */ + void _heat_eqn_array_reg() { + + int mech_type = nrn_get_mechtype("heat_eqn_array"); + heat_eqn_array_global.mech_type = mech_type; + if (mech_type == -1) { + return; + } + + _nrn_layout_reg(mech_type, 0); + register_mech(mechanism_info, nrn_alloc_heat_eqn_array, nullptr, nullptr, nrn_state_heat_eqn_array, nrn_init_heat_eqn_array, nrn_private_constructor_heat_eqn_array, nrn_private_destructor_heat_eqn_array, first_pointer_var_index(), 1); + + hoc_register_prop_size(mech_type, float_variables_size(), int_variables_size()); + hoc_register_var(hoc_scalar_double, hoc_vector_double, NULL); + } +} diff --git a/longitudinal_diffusion/coreneuron/heat_eqn_function.cpp b/longitudinal_diffusion/coreneuron/heat_eqn_function.cpp new file mode 100644 index 00000000..3d57c1b0 --- /dev/null +++ b/longitudinal_diffusion/coreneuron/heat_eqn_function.cpp @@ -0,0 +1,5 @@ +[NMODL] [error] :: Code incompatibility detected +[NMODL] [error] :: Cannot translate mod file to .cpp file +[NMODL] [error] :: Fix the following errors and try again +[NMODL] [error] :: Code Incompatibility :: "g_mu" variable found at [4.12-15] should be defined as a RANGE variable instead of GLOBAL to enable backend transformations +[NMODL] [error] :: Code Incompatibility :: "g_vol" variable found at [4.18-22] should be defined as a RANGE variable instead of GLOBAL to enable backend transformations diff --git a/longitudinal_diffusion/coreneuron/heat_eqn_global.cpp b/longitudinal_diffusion/coreneuron/heat_eqn_global.cpp new file mode 100644 index 00000000..da8b5be1 --- /dev/null +++ b/longitudinal_diffusion/coreneuron/heat_eqn_global.cpp @@ -0,0 +1,725 @@ +/********************************************************* +Model Name : heat_eqn_global +Filename : heat_eqn_global.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : CoreNEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + + +namespace coreneuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_global", + 0, + "x_heat_eqn_global", + 0, + "X_heat_eqn_global", + 0, + 0 + }; + + + /** all global variables */ + struct heat_eqn_global_Store { + double X0{}; + int reset{}; + int mech_type{}; + double mu{2}; + double vol{0.01}; + int slist1[1]{1}; + int dlist1[1]{2}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_global_Store heat_eqn_global_global; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_global_Instance { + double* x{}; + double* X{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_global_Store* global{&heat_eqn_global_global}; + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"mu_heat_eqn_global", &heat_eqn_global_global.mu}, + {"vol_heat_eqn_global", &heat_eqn_global_global.vol}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + static inline int first_pointer_var_index() { + return -1; + } + + + static inline int first_random_var_index() { + return -1; + } + + + static inline int float_variables_size() { + return 5; + } + + + static inline int int_variables_size() { + return 0; + } + + + static inline int get_mech_type() { + return heat_eqn_global_global.mech_type; + } + + + static inline Memb_list* get_memb_list(NrnThread* nt) { + if (!nt->_ml_list) { + return nullptr; + } + return nt->_ml_list[get_mech_type()]; + } + + + static inline void* mem_alloc(size_t num, size_t size, size_t alignment = 64) { + size_t aligned_size = ((num*size + alignment - 1) / alignment) * alignment; + void* ptr = aligned_alloc(alignment, aligned_size); + memset(ptr, 0, aligned_size); + return ptr; + } + + + static inline void mem_free(void* ptr) { + free(ptr); + } + + + static inline void coreneuron_abort() { + abort(); + } + + // Allocate instance structure + static void nrn_private_constructor_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + assert(!ml->instance); + assert(!ml->global_variables); + assert(ml->global_variables_size == 0); + auto* const inst = new heat_eqn_global_Instance{}; + assert(inst->global == &heat_eqn_global_global); + ml->instance = inst; + ml->global_variables = inst->global; + ml->global_variables_size = sizeof(heat_eqn_global_Store); + } + + // Deallocate the instance structure + static void nrn_private_destructor_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_global_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_global_Store)); + delete inst; + ml->instance = nullptr; + ml->global_variables = nullptr; + ml->global_variables_size = 0; + } + + /** initialize mechanism instance variables */ + static inline void setup_instance(NrnThread* nt, Memb_list* ml) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_global_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_global_Store)); + int pnodecount = ml->_nodecount_padded; + Datum* indexes = ml->pdata; + inst->x = ml->data+0*pnodecount; + inst->X = ml->data+1*pnodecount; + inst->DX = ml->data+2*pnodecount; + inst->v_unused = ml->data+3*pnodecount; + inst->g_unused = ml->data+4*pnodecount; + } + + + + static void nrn_alloc_heat_eqn_global(double* data, Datum* indexes, int type) { + // do nothing + } + + + void nrn_constructor_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + void nrn_destructor_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + struct functor_heat_eqn_global_0 { + NrnThread* nt; + heat_eqn_global_Instance* inst; + int id; + int pnodecount; + double v; + const Datum* indexes; + double* data; + ThreadDatum* thread; + double source0_, old_X; + + void initialize() { + inst->global->muinst->X[id]; + source0_ = 0.0; + old_X = inst->X[id]; + } + + functor_heat_eqn_global_0(NrnThread* nt, heat_eqn_global_Instance* inst, int id, int pnodecount, double v, const Datum* indexes, double* data, ThreadDatum* thread) + : nt(nt), inst(inst), id(id), pnodecount(pnodecount), v(v), indexes(indexes), data(data), thread(thread) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / inst->global->vol + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** initialize channel */ + void nrn_init_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + + setup_instance(nt, ml); + auto* const inst = static_cast(ml->instance); + + if (_nrn_skip_initmodel == 0) { + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + inst->X[id] = inst->global->X0; + if (inst->x[id] < 0.5) { + inst->X[id] = 1.0; + } else { + inst->X[id] = 0.0; + } + } + } + } + + + /** update state */ + void nrn_state_heat_eqn_global(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst->X[id]; + // call newton solver + functor_heat_eqn_global_0 newton_functor(nt, inst, id, pnodecount, v, indexes, data, thread); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst->X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + /** register channel with the simulator */ + void _heat_eqn_global_reg() { + + int mech_type = nrn_get_mechtype("heat_eqn_global"); + heat_eqn_global_global.mech_type = mech_type; + if (mech_type == -1) { + return; + } + + _nrn_layout_reg(mech_type, 0); + register_mech(mechanism_info, nrn_alloc_heat_eqn_global, nullptr, nullptr, nrn_state_heat_eqn_global, nrn_init_heat_eqn_global, nrn_private_constructor_heat_eqn_global, nrn_private_destructor_heat_eqn_global, first_pointer_var_index(), 1); + + hoc_register_prop_size(mech_type, float_variables_size(), int_variables_size()); + hoc_register_var(hoc_scalar_double, hoc_vector_double, NULL); + } +} diff --git a/longitudinal_diffusion/coreneuron/heat_eqn_scalar.cpp b/longitudinal_diffusion/coreneuron/heat_eqn_scalar.cpp new file mode 100644 index 00000000..340d3afa --- /dev/null +++ b/longitudinal_diffusion/coreneuron/heat_eqn_scalar.cpp @@ -0,0 +1,727 @@ +/********************************************************* +Model Name : heat_eqn_scalar +Filename : heat_eqn_scalar.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : CoreNEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + + +namespace coreneuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_scalar", + 0, + "x_heat_eqn_scalar", + 0, + "X_heat_eqn_scalar", + 0, + 0 + }; + + + /** all global variables */ + struct heat_eqn_scalar_Store { + double X0{}; + int reset{}; + int mech_type{}; + int slist1[1]{1}; + int dlist1[1]{4}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_scalar_Store heat_eqn_scalar_global; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_scalar_Instance { + double* x{}; + double* X{}; + double* mu{}; + double* vol{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_scalar_Store* global{&heat_eqn_scalar_global}; + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + static inline int first_pointer_var_index() { + return -1; + } + + + static inline int first_random_var_index() { + return -1; + } + + + static inline int float_variables_size() { + return 7; + } + + + static inline int int_variables_size() { + return 0; + } + + + static inline int get_mech_type() { + return heat_eqn_scalar_global.mech_type; + } + + + static inline Memb_list* get_memb_list(NrnThread* nt) { + if (!nt->_ml_list) { + return nullptr; + } + return nt->_ml_list[get_mech_type()]; + } + + + static inline void* mem_alloc(size_t num, size_t size, size_t alignment = 64) { + size_t aligned_size = ((num*size + alignment - 1) / alignment) * alignment; + void* ptr = aligned_alloc(alignment, aligned_size); + memset(ptr, 0, aligned_size); + return ptr; + } + + + static inline void mem_free(void* ptr) { + free(ptr); + } + + + static inline void coreneuron_abort() { + abort(); + } + + // Allocate instance structure + static void nrn_private_constructor_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + assert(!ml->instance); + assert(!ml->global_variables); + assert(ml->global_variables_size == 0); + auto* const inst = new heat_eqn_scalar_Instance{}; + assert(inst->global == &heat_eqn_scalar_global); + ml->instance = inst; + ml->global_variables = inst->global; + ml->global_variables_size = sizeof(heat_eqn_scalar_Store); + } + + // Deallocate the instance structure + static void nrn_private_destructor_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_scalar_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_scalar_Store)); + delete inst; + ml->instance = nullptr; + ml->global_variables = nullptr; + ml->global_variables_size = 0; + } + + /** initialize mechanism instance variables */ + static inline void setup_instance(NrnThread* nt, Memb_list* ml) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &heat_eqn_scalar_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(heat_eqn_scalar_Store)); + int pnodecount = ml->_nodecount_padded; + Datum* indexes = ml->pdata; + inst->x = ml->data+0*pnodecount; + inst->X = ml->data+1*pnodecount; + inst->mu = ml->data+2*pnodecount; + inst->vol = ml->data+3*pnodecount; + inst->DX = ml->data+4*pnodecount; + inst->v_unused = ml->data+5*pnodecount; + inst->g_unused = ml->data+6*pnodecount; + } + + + + static void nrn_alloc_heat_eqn_scalar(double* data, Datum* indexes, int type) { + // do nothing + } + + + void nrn_constructor_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + void nrn_destructor_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + struct functor_heat_eqn_scalar_0 { + NrnThread* nt; + heat_eqn_scalar_Instance* inst; + int id; + int pnodecount; + double v; + const Datum* indexes; + double* data; + ThreadDatum* thread; + double source0_, old_X; + + void initialize() { + inst->mu[id]inst->X[id]; + source0_ = 0.0; + old_X = inst->X[id]; + } + + functor_heat_eqn_scalar_0(NrnThread* nt, heat_eqn_scalar_Instance* inst, int id, int pnodecount, double v, const Datum* indexes, double* data, ThreadDatum* thread) + : nt(nt), inst(inst), id(id), pnodecount(pnodecount), v(v), indexes(indexes), data(data), thread(thread) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / inst->vol[id] + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** initialize channel */ + void nrn_init_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + + setup_instance(nt, ml); + auto* const inst = static_cast(ml->instance); + + if (_nrn_skip_initmodel == 0) { + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + inst->X[id] = inst->global->X0; + inst->mu[id] = 1.1; + inst->vol[id] = 0.01; + if (inst->x[id] < 0.5) { + inst->X[id] = 1.0; + } else { + inst->X[id] = 0.0; + } + } + } + } + + + /** update state */ + void nrn_state_heat_eqn_scalar(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst->X[id]; + // call newton solver + functor_heat_eqn_scalar_0 newton_functor(nt, inst, id, pnodecount, v, indexes, data, thread); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst->X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + /** register channel with the simulator */ + void _heat_eqn_scalar_reg() { + + int mech_type = nrn_get_mechtype("heat_eqn_scalar"); + heat_eqn_scalar_global.mech_type = mech_type; + if (mech_type == -1) { + return; + } + + _nrn_layout_reg(mech_type, 0); + register_mech(mechanism_info, nrn_alloc_heat_eqn_scalar, nullptr, nullptr, nrn_state_heat_eqn_scalar, nrn_init_heat_eqn_scalar, nrn_private_constructor_heat_eqn_scalar, nrn_private_destructor_heat_eqn_scalar, first_pointer_var_index(), 1); + + hoc_register_prop_size(mech_type, float_variables_size(), int_variables_size()); + hoc_register_var(hoc_scalar_double, hoc_vector_double, NULL); + } +} diff --git a/longitudinal_diffusion/coreneuron/heat_eqn_thread_vars.cpp b/longitudinal_diffusion/coreneuron/heat_eqn_thread_vars.cpp new file mode 100644 index 00000000..3f077bc2 --- /dev/null +++ b/longitudinal_diffusion/coreneuron/heat_eqn_thread_vars.cpp @@ -0,0 +1,5 @@ +[NMODL] [error] :: Code incompatibility detected +[NMODL] [error] :: Cannot translate mod file to .cpp file +[NMODL] [error] :: Fix the following errors and try again +[NMODL] [error] :: Code Incompatibility :: "mu" variable found at [4.12-13] should be defined as a RANGE variable instead of GLOBAL to enable backend transformations +[NMODL] [error] :: Code Incompatibility :: "vol" variable found at [4.16-18] should be defined as a RANGE variable instead of GLOBAL to enable backend transformations diff --git a/longitudinal_diffusion/neuron/heat_eqn_array.cpp b/longitudinal_diffusion/neuron/heat_eqn_array.cpp new file mode 100644 index 00000000..2cbb6266 --- /dev/null +++ b/longitudinal_diffusion/neuron/heat_eqn_array.cpp @@ -0,0 +1,794 @@ +/********************************************************* +Model Name : heat_eqn_array +Filename : heat_eqn_array.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 0; +static constexpr auto number_of_floating_point_variables = 7; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +Prop* hoc_getdata_range(int type); +extern Node* nrn_alloc_node_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_array", + 0, + "x_heat_eqn_array", + 0, + "X_heat_eqn_array[4]", + 0, + 0 + }; + + + /* NEURON global variables */ + static neuron::container::field_index _slist1[4], _dlist1[4]; + static int mech_type; + static Prop* _extcall_prop; + /* _prop_id kind of shadows _extcall_prop to allow validity checking. */ + static _nrn_non_owning_id_without_container _prop_id{}; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct heat_eqn_array_Store { + double kf{0}; + double kb{0}; + double X0{0}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_array_Store heat_eqn_array_global; + auto kf_heat_eqn_array() -> std::decay::type { + return heat_eqn_array_global.kf; + } + auto kb_heat_eqn_array() -> std::decay::type { + return heat_eqn_array_global.kb; + } + auto X0_heat_eqn_array() -> std::decay::type { + return heat_eqn_array_global.X0; + } + + static std::vector _parameter_defaults = { + }; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_array_Instance { + double* x{}; + double* X{}; + double* mu{}; + double* vol{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_array_Store* global{&heat_eqn_array_global}; + }; + + + struct heat_eqn_array_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + static heat_eqn_array_Instance make_instance_heat_eqn_array(_nrn_mechanism_cache_range& _lmc) { + return heat_eqn_array_Instance { + _lmc.template fpfield_ptr<0>(), + _lmc.template data_array_ptr<1, 4>(), + _lmc.template data_array_ptr<2, 4>(), + _lmc.template data_array_ptr<3, 4>(), + _lmc.template data_array_ptr<4, 4>(), + _lmc.template fpfield_ptr<5>(), + _lmc.template fpfield_ptr<6>() + }; + } + + + static heat_eqn_array_NodeData make_node_data_heat_eqn_array(NrnThread& nt, Memb_list& _ml_arg) { + return heat_eqn_array_NodeData { + _ml_arg.nodeindices, + nt.node_voltage_storage(), + nt.node_d_storage(), + nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + static heat_eqn_array_NodeData make_node_data_heat_eqn_array(Prop * _prop) { + static std::vector node_index{0}; + Node* _node = _nrn_mechanism_access_node(_prop); + return heat_eqn_array_NodeData { + node_index.data(), + &_nrn_mechanism_access_voltage(_node), + &_nrn_mechanism_access_d(_node), + &_nrn_mechanism_access_rhs(_node), + 1 + }; + } + + void nrn_destructor_heat_eqn_array(Prop* prop); + + + static void nrn_alloc_heat_eqn_array(Prop* _prop) { + Datum *_ppvar = nullptr; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const _iml = 0; + assert(_nrn_mechanism_get_num_vars(_prop) == 7); + /*initialize range parameters*/ + } + + + /* Mechanism procedures and functions */ + static void* _diffusion_space_X; + static double _diffusion_coefficient_X(int _i, Memb_list* _ml_arg, size_t id, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* /* _thread */, NrnThread* nt, const _nrn_model_sorted_token& _sorted_token) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_array(_lmc); + auto node_data = make_node_data_heat_eqn_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + *_pdvol= (inst.vol+id*4)[static_cast(_i)]; + *_pdfcdc = 0.0; + return (inst.mu+id*4)[static_cast(_i)]; + } + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + for(size_t _i = 0; _i < 4; ++_i) { + (*_f)(mech_type, _diffusion_coefficient_X, &_diffusion_space_X, _i, /* x pos */ 1, /* Dx pos */ 4, _sorted_token, _nt); + } + } + + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + _extcall_prop = _prop; + _prop_id = _nrn_get_prop_id(_prop); + } + static void _hoc_setdata() { + Prop *_prop = hoc_getdata_range(mech_type); + _setdata(_prop); + hoc_retpushx(1.); + } + + + struct functor_heat_eqn_array_0 { + _nrn_mechanism_cache_range& _lmc; + heat_eqn_array_Instance& inst; + heat_eqn_array_NodeData& node_data; + size_t id; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + double v; + double kf0_, kb0_, kf1_, kb1_, kf2_, kb2_, old_X_0, old_X_1, old_X_2, old_X_3; + + void initialize() { + ; + { + kf0_ = inst.global->kf; + kb0_ = inst.global->kb; + kf1_ = inst.global->kf; + kb1_ = inst.global->kb; + kf2_ = inst.global->kf; + kb2_ = inst.global->kb; + } + old_X_0 = (inst.X+id*4)[static_cast(0)]; + old_X_1 = (inst.X+id*4)[static_cast(1)]; + old_X_2 = (inst.X+id*4)[static_cast(2)]; + old_X_3 = (inst.X+id*4)[static_cast(3)]; + } + + functor_heat_eqn_array_0(_nrn_mechanism_cache_range& _lmc, heat_eqn_array_Instance& inst, heat_eqn_array_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double v) + : _lmc(_lmc), inst(inst), node_data(node_data), id(id), _ppvar(_ppvar), _thread(_thread), nt(nt), v(v) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_dx[1] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[1])); + nmodl_eigen_dx[2] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[2])); + nmodl_eigen_dx[3] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[3])); + nmodl_eigen_f[static_cast(0)] = (nt->_dt * ( -nmodl_eigen_x[static_cast(0)] * kf0_ + nmodl_eigen_x[static_cast(1)] * kb0_) + ( -nmodl_eigen_x[static_cast(0)] + old_X_0) * (inst.vol+id*4)[static_cast(0)]) / (nt->_dt * (inst.vol+id*4)[static_cast(0)]); + nmodl_eigen_j[static_cast(0)] = -kf0_ / (inst.vol+id*4)[static_cast(0)] - 1.0 / nt->_dt; + nmodl_eigen_j[static_cast(4)] = kb0_ / (inst.vol+id*4)[static_cast(0)]; + nmodl_eigen_j[static_cast(8)] = 0.0; + nmodl_eigen_j[static_cast(12)] = 0.0; + nmodl_eigen_f[static_cast(1)] = (nt->_dt * (nmodl_eigen_x[static_cast(0)] * kf0_ - nmodl_eigen_x[static_cast(1)] * kb0_ - nmodl_eigen_x[static_cast(1)] * kf1_ + nmodl_eigen_x[static_cast(2)] * kb1_) + ( -nmodl_eigen_x[static_cast(1)] + old_X_1) * (inst.vol+id*4)[static_cast(1)]) / (nt->_dt * (inst.vol+id*4)[static_cast(1)]); + nmodl_eigen_j[static_cast(1)] = kf0_ / (inst.vol+id*4)[static_cast(1)]; + nmodl_eigen_j[static_cast(5)] = (nt->_dt * ( -kb0_ - kf1_) - (inst.vol+id*4)[static_cast(1)]) / (nt->_dt * (inst.vol+id*4)[static_cast(1)]); + nmodl_eigen_j[static_cast(9)] = kb1_ / (inst.vol+id*4)[static_cast(1)]; + nmodl_eigen_j[static_cast(13)] = 0.0; + nmodl_eigen_f[static_cast(2)] = (nt->_dt * (nmodl_eigen_x[static_cast(1)] * kf1_ - nmodl_eigen_x[static_cast(2)] * kb1_ - nmodl_eigen_x[static_cast(2)] * kf2_ + nmodl_eigen_x[static_cast(3)] * kb2_) + ( -nmodl_eigen_x[static_cast(2)] + old_X_2) * (inst.vol+id*4)[static_cast(2)]) / (nt->_dt * (inst.vol+id*4)[static_cast(2)]); + nmodl_eigen_j[static_cast(2)] = 0.0; + nmodl_eigen_j[static_cast(6)] = kf1_ / (inst.vol+id*4)[static_cast(2)]; + nmodl_eigen_j[static_cast(10)] = (nt->_dt * ( -kb1_ - kf2_) - (inst.vol+id*4)[static_cast(2)]) / (nt->_dt * (inst.vol+id*4)[static_cast(2)]); + nmodl_eigen_j[static_cast(14)] = kb2_ / (inst.vol+id*4)[static_cast(2)]; + nmodl_eigen_f[static_cast(3)] = (nt->_dt * (nmodl_eigen_x[static_cast(2)] * kf2_ - nmodl_eigen_x[static_cast(3)] * kb2_) + ( -nmodl_eigen_x[static_cast(3)] + old_X_3) * (inst.vol+id*4)[static_cast(3)]) / (nt->_dt * (inst.vol+id*4)[static_cast(3)]); + nmodl_eigen_j[static_cast(3)] = 0.0; + nmodl_eigen_j[static_cast(7)] = 0.0; + nmodl_eigen_j[static_cast(11)] = kf2_ / (inst.vol+id*4)[static_cast(3)]; + nmodl_eigen_j[static_cast(15)] = -kb2_ / (inst.vol+id*4)[static_cast(3)] - 1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"kf_heat_eqn_array", &heat_eqn_array_global.kf}, + {"kb_heat_eqn_array", &heat_eqn_array_global.kb}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {"setdata_heat_eqn_array", _hoc_setdata}, + {nullptr, nullptr} + }; + static NPyDirectMechFunc npy_direct_func_proc[] = { + {nullptr, nullptr} + }; + + + void nrn_init_heat_eqn_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_array(_lmc); + auto node_data = make_node_data_heat_eqn_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + auto* _ppvar = _ml_arg->pdata[id]; + int node_id = node_data.nodeindices[id]; + auto v = node_data.node_voltages[node_id]; + (inst.X+id*4)[0] = inst.global->X0; + (inst.X+id*4)[1] = inst.global->X0; + (inst.X+id*4)[2] = inst.global->X0; + (inst.X+id*4)[3] = inst.global->X0; + for (int i = 0; i <= 4 - 1; i++) { + (inst.mu+id*4)[static_cast(i)] = 1.0 + i; + (inst.vol+id*4)[static_cast(i)] = 0.01 / (i + 1.0); + if (inst.x[id] < 0.5) { + (inst.X+id*4)[static_cast(i)] = 1.0 + i; + } else { + (inst.X+id*4)[static_cast(i)] = 0.0; + } + } + } + } + + + void nrn_state_heat_eqn_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_array(_lmc); + auto node_data = make_node_data_heat_eqn_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = (inst.X+id*4)[static_cast(0)]; + nmodl_eigen_x[static_cast(1)] = (inst.X+id*4)[static_cast(1)]; + nmodl_eigen_x[static_cast(2)] = (inst.X+id*4)[static_cast(2)]; + nmodl_eigen_x[static_cast(3)] = (inst.X+id*4)[static_cast(3)]; + // call newton solver + functor_heat_eqn_array_0 newton_functor(_lmc, inst, node_data, id, _ppvar, _thread, nt, v); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + (inst.X+id*4)[static_cast(0)] = nmodl_eigen_x[static_cast(0)]; + (inst.X+id*4)[static_cast(1)] = nmodl_eigen_x[static_cast(1)]; + (inst.X+id*4)[static_cast(2)] = nmodl_eigen_x[static_cast(2)]; + (inst.X+id*4)[static_cast(3)] = nmodl_eigen_x[static_cast(3)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + static void nrn_jacob_heat_eqn_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_array(_lmc); + auto node_data = make_node_data_heat_eqn_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + node_data.node_diagonal[node_id] += inst.g_unused[id]; + } + } + void nrn_destructor_heat_eqn_array(Prop* prop) { + Datum* _ppvar = _nrn_mechanism_access_dparam(prop); + _nrn_mechanism_cache_instance _lmc{prop}; + const size_t id = 0; + auto inst = make_instance_heat_eqn_array(_lmc); + auto node_data = make_node_data_heat_eqn_array(prop); + + } + + + static void _initlists() { + for (int _i = 0; _i < 4; ++_i) { + /* X[4] */ + _slist1[0+_i] = {1, _i}; + /* DX[4] */ + _dlist1[0+_i] = {4, _i}; + } + } + + + /** register channel with the simulator */ + extern "C" void _heat_eqn_array_reg() { + _initlists(); + + register_mech(mechanism_info, nrn_alloc_heat_eqn_array, nullptr, nrn_jacob_heat_eqn_array, nrn_state_heat_eqn_array, nrn_init_heat_eqn_array, -1, 1); + + mech_type = nrn_get_mechtype(mechanism_info[1]); + hoc_register_parm_default(mech_type, &_parameter_defaults); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"x"} /* 0 */, + _nrn_mechanism_field{"X", 4} /* 1 */, + _nrn_mechanism_field{"mu", 4} /* 2 */, + _nrn_mechanism_field{"vol", 4} /* 3 */, + _nrn_mechanism_field{"DX", 4} /* 4 */, + _nrn_mechanism_field{"v_unused"} /* 5 */, + _nrn_mechanism_field{"g_unused"} /* 6 */ + ); + + hoc_register_prop_size(mech_type, 19, 0); + hoc_register_ldifus1(_apply_diffusion_function); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + hoc_register_npy_direct(mech_type, npy_direct_func_proc); + } +} diff --git a/longitudinal_diffusion/neuron/heat_eqn_function.cpp b/longitudinal_diffusion/neuron/heat_eqn_function.cpp new file mode 100644 index 00000000..09fc3d6d --- /dev/null +++ b/longitudinal_diffusion/neuron/heat_eqn_function.cpp @@ -0,0 +1,938 @@ +/********************************************************* +Model Name : heat_eqn_function +Filename : heat_eqn_function.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" +extern void _nrn_thread_reg(int, int, void(*)(Datum*)); + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 0; +static constexpr auto number_of_floating_point_variables = 5; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +Prop* hoc_getdata_range(int type); +extern Node* nrn_alloc_node_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_function", + 0, + "x_heat_eqn_function", + 0, + "X_heat_eqn_function", + 0, + 0 + }; + + + /* NEURON global variables */ + static neuron::container::field_index _slist1[1], _dlist1[1]; + static int mech_type; + static Prop* _extcall_prop; + /* _prop_id kind of shadows _extcall_prop to allow validity checking. */ + static _nrn_non_owning_id_without_container _prop_id{}; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct heat_eqn_function_Store { + double thread_data_in_use{0}; + double thread_data[2] /* TODO init const-array */; + double X0{0}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_function_Store heat_eqn_function_global; + auto thread_data_in_use_heat_eqn_function() -> std::decay::type { + return heat_eqn_function_global.thread_data_in_use; + } + auto thread_data_heat_eqn_function() -> std::decay::type { + return heat_eqn_function_global.thread_data; + } + auto X0_heat_eqn_function() -> std::decay::type { + return heat_eqn_function_global.X0; + } + + static std::vector _parameter_defaults = { + }; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_function_Instance { + double* x{}; + double* X{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_function_Store* global{&heat_eqn_function_global}; + }; + + + struct heat_eqn_function_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + struct heat_eqn_function_ThreadVariables { + double * thread_data; + + double * g_vol_ptr(size_t id) { + return thread_data + 0 + (id % 1); + } + double & g_vol(size_t id) { + return thread_data[0 + (id % 1)]; + } + double * g_mu_ptr(size_t id) { + return thread_data + 1 + (id % 1); + } + double & g_mu(size_t id) { + return thread_data[1 + (id % 1)]; + } + + heat_eqn_function_ThreadVariables(double * const thread_data) { + this->thread_data = thread_data; + } + }; + + + static heat_eqn_function_Instance make_instance_heat_eqn_function(_nrn_mechanism_cache_range& _lmc) { + return heat_eqn_function_Instance { + _lmc.template fpfield_ptr<0>(), + _lmc.template fpfield_ptr<1>(), + _lmc.template fpfield_ptr<2>(), + _lmc.template fpfield_ptr<3>(), + _lmc.template fpfield_ptr<4>() + }; + } + + + static heat_eqn_function_NodeData make_node_data_heat_eqn_function(NrnThread& nt, Memb_list& _ml_arg) { + return heat_eqn_function_NodeData { + _ml_arg.nodeindices, + nt.node_voltage_storage(), + nt.node_d_storage(), + nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + static heat_eqn_function_NodeData make_node_data_heat_eqn_function(Prop * _prop) { + static std::vector node_index{0}; + Node* _node = _nrn_mechanism_access_node(_prop); + return heat_eqn_function_NodeData { + node_index.data(), + &_nrn_mechanism_access_voltage(_node), + &_nrn_mechanism_access_d(_node), + &_nrn_mechanism_access_rhs(_node), + 1 + }; + } + + void nrn_destructor_heat_eqn_function(Prop* prop); + + + static void nrn_alloc_heat_eqn_function(Prop* _prop) { + Datum *_ppvar = nullptr; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const _iml = 0; + assert(_nrn_mechanism_get_num_vars(_prop) == 5); + /*initialize range parameters*/ + } + + + /* Mechanism procedures and functions */ + inline double factor_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx); + inline double vol_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx); + inline double mu_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx); + static void* _diffusion_space_X; + static double _diffusion_coefficient_X(int _i, Memb_list* _ml_arg, size_t id, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* /* _thread */, NrnThread* nt, const _nrn_model_sorted_token& _sorted_token) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + *_pdvol= vol_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, inst.x[id]); + *_pdfcdc = 0.0; + return mu_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, factor_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, inst.x[id])); + } + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + for(size_t _i = 0; _i < 1; ++_i) { + (*_f)(mech_type, _diffusion_coefficient_X, &_diffusion_space_X, _i, /* x pos */ 1, /* Dx pos */ 2, _sorted_token, _nt); + } + } + + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + _extcall_prop = _prop; + _prop_id = _nrn_get_prop_id(_prop); + } + static void _hoc_setdata() { + Prop *_prop = hoc_getdata_range(mech_type); + _setdata(_prop); + hoc_retpushx(1.); + } + + + struct functor_heat_eqn_function_0 { + _nrn_mechanism_cache_range& _lmc; + heat_eqn_function_Instance& inst; + heat_eqn_function_NodeData& node_data; + size_t id; + Datum* _ppvar; + Datum* _thread; + heat_eqn_function_ThreadVariables& _thread_vars; + NrnThread* nt; + double v; + double source0_, old_X; + + void initialize() { + ; + source0_ = 0.0; + old_X = inst.X[id]; + } + + functor_heat_eqn_function_0(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double v) + : _lmc(_lmc), inst(inst), node_data(node_data), id(id), _ppvar(_ppvar), _thread(_thread), _thread_vars(_thread_vars), nt(nt), v(v) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / vol_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, inst.x[id]) + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"g_vol_heat_eqn_function", &heat_eqn_function_global.thread_data[0]}, + {"g_mu_heat_eqn_function", &heat_eqn_function_global.thread_data[1]}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + static void _hoc_factor(void); + static double _npy_factor(Prop*); + static void _hoc_vol(void); + static double _npy_vol(Prop*); + static void _hoc_mu(void); + static double _npy_mu(Prop*); + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {"setdata_heat_eqn_function", _hoc_setdata}, + {"factor_heat_eqn_function", _hoc_factor}, + {"vol_heat_eqn_function", _hoc_vol}, + {"mu_heat_eqn_function", _hoc_mu}, + {nullptr, nullptr} + }; + static NPyDirectMechFunc npy_direct_func_proc[] = { + {"factor", _npy_factor}, + {"vol", _npy_vol}, + {"mu", _npy_mu}, + {nullptr, nullptr} + }; + static void thread_mem_init(Datum* _thread) { + if(heat_eqn_function_global.thread_data_in_use) { + _thread[0] = {neuron::container::do_not_search, new double[2]{}}; + } + else { + _thread[0] = {neuron::container::do_not_search, heat_eqn_function_global.thread_data}; + heat_eqn_function_global.thread_data_in_use = 1; + } + } + static void thread_mem_cleanup(Datum* _thread) { + double * _thread_data_ptr = _thread[0].get(); + if(_thread_data_ptr == heat_eqn_function_global.thread_data) { + heat_eqn_function_global.thread_data_in_use = 0; + } + else { + delete[] _thread_data_ptr; + } + } + static void _hoc_factor(void) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + Prop* _local_prop = _prop_id ? _extcall_prop : nullptr; + _nrn_mechanism_cache_instance _lmc{_local_prop}; + size_t const id{}; + _ppvar = _local_prop ? _nrn_mechanism_access_dparam(_local_prop) : nullptr; + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_local_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = factor_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + hoc_retpushx(_r); + } + static double _npy_factor(Prop* _prop) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const id = 0; + _ppvar = _nrn_mechanism_access_dparam(_prop); + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = factor_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + return(_r); + } + static void _hoc_vol(void) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + Prop* _local_prop = _prop_id ? _extcall_prop : nullptr; + _nrn_mechanism_cache_instance _lmc{_local_prop}; + size_t const id{}; + _ppvar = _local_prop ? _nrn_mechanism_access_dparam(_local_prop) : nullptr; + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_local_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = vol_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + hoc_retpushx(_r); + } + static double _npy_vol(Prop* _prop) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const id = 0; + _ppvar = _nrn_mechanism_access_dparam(_prop); + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = vol_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + return(_r); + } + static void _hoc_mu(void) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + Prop* _local_prop = _prop_id ? _extcall_prop : nullptr; + _nrn_mechanism_cache_instance _lmc{_local_prop}; + size_t const id{}; + _ppvar = _local_prop ? _nrn_mechanism_access_dparam(_local_prop) : nullptr; + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_local_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = mu_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + hoc_retpushx(_r); + } + static double _npy_mu(Prop* _prop) { + double _r{}; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const id = 0; + _ppvar = _nrn_mechanism_access_dparam(_prop); + _thread = _extcall_thread.data(); + nt = nrn_threads; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(_prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + _r = mu_heat_eqn_function(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, *getarg(1)); + return(_r); + } + + + inline double factor_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx) { + double ret_factor = 0.0; + auto v = node_data.node_voltages[node_data.nodeindices[id]]; + if (_lx < 0.25) { + ret_factor = 0.0; + } else { + ret_factor = 10.0 * (_lx - 0.25); + } + return ret_factor; + } + + + inline double vol_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx) { + double ret_vol = 0.0; + auto v = node_data.node_voltages[node_data.nodeindices[id]]; + ret_vol = (1.0 + _lx) * _thread_vars.g_vol(id); + return ret_vol; + } + + + inline double mu_heat_eqn_function(_nrn_mechanism_cache_range& _lmc, heat_eqn_function_Instance& inst, heat_eqn_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_function_ThreadVariables& _thread_vars, NrnThread* nt, double _lx) { + double ret_mu = 0.0; + auto v = node_data.node_voltages[node_data.nodeindices[id]]; + ret_mu = _lx * _thread_vars.g_mu(id); + return ret_mu; + } + + + void nrn_init_heat_eqn_function(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + auto* _ppvar = _ml_arg->pdata[id]; + int node_id = node_data.nodeindices[id]; + auto v = node_data.node_voltages[node_id]; + inst.X[id] = inst.global->X0; + _thread_vars.g_mu(id) = 1.1; + _thread_vars.g_vol(id) = 0.01; + if (inst.x[id] < 0.5) { + inst.X[id] = 1.0; + } else { + inst.X[id] = 0.0; + } + } + } + + + void nrn_state_heat_eqn_function(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst.X[id]; + // call newton solver + functor_heat_eqn_function_0 newton_functor(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, v); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst.X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + static void nrn_jacob_heat_eqn_function(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_function_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + node_data.node_diagonal[node_id] += inst.g_unused[id]; + } + } + void nrn_destructor_heat_eqn_function(Prop* prop) { + Datum* _ppvar = _nrn_mechanism_access_dparam(prop); + _nrn_mechanism_cache_instance _lmc{prop}; + const size_t id = 0; + auto inst = make_instance_heat_eqn_function(_lmc); + auto node_data = make_node_data_heat_eqn_function(prop); + auto _thread_vars = heat_eqn_function_ThreadVariables(heat_eqn_function_global.thread_data); + + } + + + static void _initlists() { + /* X */ + _slist1[0] = {1, 0}; + /* DX */ + _dlist1[0] = {2, 0}; + } + + + /** register channel with the simulator */ + extern "C" void _heat_eqn_function_reg() { + _initlists(); + + register_mech(mechanism_info, nrn_alloc_heat_eqn_function, nullptr, nrn_jacob_heat_eqn_function, nrn_state_heat_eqn_function, nrn_init_heat_eqn_function, -1, 2); + _extcall_thread.resize(2); + thread_mem_init(_extcall_thread.data()); + heat_eqn_function_global.thread_data_in_use = 0; + + mech_type = nrn_get_mechtype(mechanism_info[1]); + hoc_register_parm_default(mech_type, &_parameter_defaults); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"x"} /* 0 */, + _nrn_mechanism_field{"X"} /* 1 */, + _nrn_mechanism_field{"DX"} /* 2 */, + _nrn_mechanism_field{"v_unused"} /* 3 */, + _nrn_mechanism_field{"g_unused"} /* 4 */ + ); + + hoc_register_prop_size(mech_type, 5, 0); + hoc_register_ldifus1(_apply_diffusion_function); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + hoc_register_npy_direct(mech_type, npy_direct_func_proc); + _nrn_thread_reg(mech_type, 1, thread_mem_init); + _nrn_thread_reg(mech_type, 0, thread_mem_cleanup); + } +} diff --git a/longitudinal_diffusion/neuron/heat_eqn_global.cpp b/longitudinal_diffusion/neuron/heat_eqn_global.cpp new file mode 100644 index 00000000..88ac1082 --- /dev/null +++ b/longitudinal_diffusion/neuron/heat_eqn_global.cpp @@ -0,0 +1,742 @@ +/********************************************************* +Model Name : heat_eqn_global +Filename : heat_eqn_global.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 0; +static constexpr auto number_of_floating_point_variables = 5; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +Prop* hoc_getdata_range(int type); +extern Node* nrn_alloc_node_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_global", + 0, + "x_heat_eqn_global", + 0, + "X_heat_eqn_global", + 0, + 0 + }; + + + /* NEURON global variables */ + static neuron::container::field_index _slist1[1], _dlist1[1]; + static int mech_type; + static Prop* _extcall_prop; + /* _prop_id kind of shadows _extcall_prop to allow validity checking. */ + static _nrn_non_owning_id_without_container _prop_id{}; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct heat_eqn_global_Store { + double mu{2}; + double vol{0.01}; + double X0{0}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_global_Store heat_eqn_global_global; + auto mu_heat_eqn_global() -> std::decay::type { + return heat_eqn_global_global.mu; + } + auto vol_heat_eqn_global() -> std::decay::type { + return heat_eqn_global_global.vol; + } + auto X0_heat_eqn_global() -> std::decay::type { + return heat_eqn_global_global.X0; + } + + static std::vector _parameter_defaults = { + }; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_global_Instance { + double* x{}; + double* X{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_global_Store* global{&heat_eqn_global_global}; + }; + + + struct heat_eqn_global_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + static heat_eqn_global_Instance make_instance_heat_eqn_global(_nrn_mechanism_cache_range& _lmc) { + return heat_eqn_global_Instance { + _lmc.template fpfield_ptr<0>(), + _lmc.template fpfield_ptr<1>(), + _lmc.template fpfield_ptr<2>(), + _lmc.template fpfield_ptr<3>(), + _lmc.template fpfield_ptr<4>() + }; + } + + + static heat_eqn_global_NodeData make_node_data_heat_eqn_global(NrnThread& nt, Memb_list& _ml_arg) { + return heat_eqn_global_NodeData { + _ml_arg.nodeindices, + nt.node_voltage_storage(), + nt.node_d_storage(), + nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + static heat_eqn_global_NodeData make_node_data_heat_eqn_global(Prop * _prop) { + static std::vector node_index{0}; + Node* _node = _nrn_mechanism_access_node(_prop); + return heat_eqn_global_NodeData { + node_index.data(), + &_nrn_mechanism_access_voltage(_node), + &_nrn_mechanism_access_d(_node), + &_nrn_mechanism_access_rhs(_node), + 1 + }; + } + + void nrn_destructor_heat_eqn_global(Prop* prop); + + + static void nrn_alloc_heat_eqn_global(Prop* _prop) { + Datum *_ppvar = nullptr; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const _iml = 0; + assert(_nrn_mechanism_get_num_vars(_prop) == 5); + /*initialize range parameters*/ + } + + + /* Mechanism procedures and functions */ + static void* _diffusion_space_X; + static double _diffusion_coefficient_X(int _i, Memb_list* _ml_arg, size_t id, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* /* _thread */, NrnThread* nt, const _nrn_model_sorted_token& _sorted_token) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_global(_lmc); + auto node_data = make_node_data_heat_eqn_global(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + *_pdvol= inst.global->vol; + *_pdfcdc = 0.0; + return inst.global->mu; + } + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + for(size_t _i = 0; _i < 1; ++_i) { + (*_f)(mech_type, _diffusion_coefficient_X, &_diffusion_space_X, _i, /* x pos */ 1, /* Dx pos */ 2, _sorted_token, _nt); + } + } + + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + _extcall_prop = _prop; + _prop_id = _nrn_get_prop_id(_prop); + } + static void _hoc_setdata() { + Prop *_prop = hoc_getdata_range(mech_type); + _setdata(_prop); + hoc_retpushx(1.); + } + + + struct functor_heat_eqn_global_0 { + _nrn_mechanism_cache_range& _lmc; + heat_eqn_global_Instance& inst; + heat_eqn_global_NodeData& node_data; + size_t id; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + double v; + double source0_, old_X; + + void initialize() { + ; + source0_ = 0.0; + old_X = inst.X[id]; + } + + functor_heat_eqn_global_0(_nrn_mechanism_cache_range& _lmc, heat_eqn_global_Instance& inst, heat_eqn_global_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double v) + : _lmc(_lmc), inst(inst), node_data(node_data), id(id), _ppvar(_ppvar), _thread(_thread), nt(nt), v(v) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / inst.global->vol + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"mu_heat_eqn_global", &heat_eqn_global_global.mu}, + {"vol_heat_eqn_global", &heat_eqn_global_global.vol}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {"setdata_heat_eqn_global", _hoc_setdata}, + {nullptr, nullptr} + }; + static NPyDirectMechFunc npy_direct_func_proc[] = { + {nullptr, nullptr} + }; + + + void nrn_init_heat_eqn_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_global(_lmc); + auto node_data = make_node_data_heat_eqn_global(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + auto* _ppvar = _ml_arg->pdata[id]; + int node_id = node_data.nodeindices[id]; + auto v = node_data.node_voltages[node_id]; + inst.X[id] = inst.global->X0; + if (inst.x[id] < 0.5) { + inst.X[id] = 1.0; + } else { + inst.X[id] = 0.0; + } + } + } + + + void nrn_state_heat_eqn_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_global(_lmc); + auto node_data = make_node_data_heat_eqn_global(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst.X[id]; + // call newton solver + functor_heat_eqn_global_0 newton_functor(_lmc, inst, node_data, id, _ppvar, _thread, nt, v); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst.X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + static void nrn_jacob_heat_eqn_global(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_global(_lmc); + auto node_data = make_node_data_heat_eqn_global(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + node_data.node_diagonal[node_id] += inst.g_unused[id]; + } + } + void nrn_destructor_heat_eqn_global(Prop* prop) { + Datum* _ppvar = _nrn_mechanism_access_dparam(prop); + _nrn_mechanism_cache_instance _lmc{prop}; + const size_t id = 0; + auto inst = make_instance_heat_eqn_global(_lmc); + auto node_data = make_node_data_heat_eqn_global(prop); + + } + + + static void _initlists() { + /* X */ + _slist1[0] = {1, 0}; + /* DX */ + _dlist1[0] = {2, 0}; + } + + + /** register channel with the simulator */ + extern "C" void _heat_eqn_global_reg() { + _initlists(); + + register_mech(mechanism_info, nrn_alloc_heat_eqn_global, nullptr, nrn_jacob_heat_eqn_global, nrn_state_heat_eqn_global, nrn_init_heat_eqn_global, -1, 1); + + mech_type = nrn_get_mechtype(mechanism_info[1]); + hoc_register_parm_default(mech_type, &_parameter_defaults); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"x"} /* 0 */, + _nrn_mechanism_field{"X"} /* 1 */, + _nrn_mechanism_field{"DX"} /* 2 */, + _nrn_mechanism_field{"v_unused"} /* 3 */, + _nrn_mechanism_field{"g_unused"} /* 4 */ + ); + + hoc_register_prop_size(mech_type, 5, 0); + hoc_register_ldifus1(_apply_diffusion_function); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + hoc_register_npy_direct(mech_type, npy_direct_func_proc); + } +} diff --git a/longitudinal_diffusion/neuron/heat_eqn_scalar.cpp b/longitudinal_diffusion/neuron/heat_eqn_scalar.cpp new file mode 100644 index 00000000..a017059a --- /dev/null +++ b/longitudinal_diffusion/neuron/heat_eqn_scalar.cpp @@ -0,0 +1,740 @@ +/********************************************************* +Model Name : heat_eqn_scalar +Filename : heat_eqn_scalar.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 0; +static constexpr auto number_of_floating_point_variables = 7; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +Prop* hoc_getdata_range(int type); +extern Node* nrn_alloc_node_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_scalar", + 0, + "x_heat_eqn_scalar", + 0, + "X_heat_eqn_scalar", + 0, + 0 + }; + + + /* NEURON global variables */ + static neuron::container::field_index _slist1[1], _dlist1[1]; + static int mech_type; + static Prop* _extcall_prop; + /* _prop_id kind of shadows _extcall_prop to allow validity checking. */ + static _nrn_non_owning_id_without_container _prop_id{}; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct heat_eqn_scalar_Store { + double X0{0}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_scalar_Store heat_eqn_scalar_global; + auto X0_heat_eqn_scalar() -> std::decay::type { + return heat_eqn_scalar_global.X0; + } + + static std::vector _parameter_defaults = { + }; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_scalar_Instance { + double* x{}; + double* X{}; + double* mu{}; + double* vol{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_scalar_Store* global{&heat_eqn_scalar_global}; + }; + + + struct heat_eqn_scalar_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + static heat_eqn_scalar_Instance make_instance_heat_eqn_scalar(_nrn_mechanism_cache_range& _lmc) { + return heat_eqn_scalar_Instance { + _lmc.template fpfield_ptr<0>(), + _lmc.template fpfield_ptr<1>(), + _lmc.template fpfield_ptr<2>(), + _lmc.template fpfield_ptr<3>(), + _lmc.template fpfield_ptr<4>(), + _lmc.template fpfield_ptr<5>(), + _lmc.template fpfield_ptr<6>() + }; + } + + + static heat_eqn_scalar_NodeData make_node_data_heat_eqn_scalar(NrnThread& nt, Memb_list& _ml_arg) { + return heat_eqn_scalar_NodeData { + _ml_arg.nodeindices, + nt.node_voltage_storage(), + nt.node_d_storage(), + nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + static heat_eqn_scalar_NodeData make_node_data_heat_eqn_scalar(Prop * _prop) { + static std::vector node_index{0}; + Node* _node = _nrn_mechanism_access_node(_prop); + return heat_eqn_scalar_NodeData { + node_index.data(), + &_nrn_mechanism_access_voltage(_node), + &_nrn_mechanism_access_d(_node), + &_nrn_mechanism_access_rhs(_node), + 1 + }; + } + + void nrn_destructor_heat_eqn_scalar(Prop* prop); + + + static void nrn_alloc_heat_eqn_scalar(Prop* _prop) { + Datum *_ppvar = nullptr; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const _iml = 0; + assert(_nrn_mechanism_get_num_vars(_prop) == 7); + /*initialize range parameters*/ + } + + + /* Mechanism procedures and functions */ + static void* _diffusion_space_X; + static double _diffusion_coefficient_X(int _i, Memb_list* _ml_arg, size_t id, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* /* _thread */, NrnThread* nt, const _nrn_model_sorted_token& _sorted_token) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_scalar(_lmc); + auto node_data = make_node_data_heat_eqn_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + *_pdvol= inst.vol[id]; + *_pdfcdc = 0.0; + return inst.mu[id]; + } + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + for(size_t _i = 0; _i < 1; ++_i) { + (*_f)(mech_type, _diffusion_coefficient_X, &_diffusion_space_X, _i, /* x pos */ 1, /* Dx pos */ 4, _sorted_token, _nt); + } + } + + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + _extcall_prop = _prop; + _prop_id = _nrn_get_prop_id(_prop); + } + static void _hoc_setdata() { + Prop *_prop = hoc_getdata_range(mech_type); + _setdata(_prop); + hoc_retpushx(1.); + } + + + struct functor_heat_eqn_scalar_0 { + _nrn_mechanism_cache_range& _lmc; + heat_eqn_scalar_Instance& inst; + heat_eqn_scalar_NodeData& node_data; + size_t id; + Datum* _ppvar; + Datum* _thread; + NrnThread* nt; + double v; + double source0_, old_X; + + void initialize() { + ; + source0_ = 0.0; + old_X = inst.X[id]; + } + + functor_heat_eqn_scalar_0(_nrn_mechanism_cache_range& _lmc, heat_eqn_scalar_Instance& inst, heat_eqn_scalar_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double v) + : _lmc(_lmc), inst(inst), node_data(node_data), id(id), _ppvar(_ppvar), _thread(_thread), nt(nt), v(v) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / inst.vol[id] + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {"setdata_heat_eqn_scalar", _hoc_setdata}, + {nullptr, nullptr} + }; + static NPyDirectMechFunc npy_direct_func_proc[] = { + {nullptr, nullptr} + }; + + + void nrn_init_heat_eqn_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_scalar(_lmc); + auto node_data = make_node_data_heat_eqn_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + auto* _ppvar = _ml_arg->pdata[id]; + int node_id = node_data.nodeindices[id]; + auto v = node_data.node_voltages[node_id]; + inst.X[id] = inst.global->X0; + inst.mu[id] = 1.1; + inst.vol[id] = 0.01; + if (inst.x[id] < 0.5) { + inst.X[id] = 1.0; + } else { + inst.X[id] = 0.0; + } + } + } + + + void nrn_state_heat_eqn_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_scalar(_lmc); + auto node_data = make_node_data_heat_eqn_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst.X[id]; + // call newton solver + functor_heat_eqn_scalar_0 newton_functor(_lmc, inst, node_data, id, _ppvar, _thread, nt, v); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst.X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + static void nrn_jacob_heat_eqn_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_scalar(_lmc); + auto node_data = make_node_data_heat_eqn_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + node_data.node_diagonal[node_id] += inst.g_unused[id]; + } + } + void nrn_destructor_heat_eqn_scalar(Prop* prop) { + Datum* _ppvar = _nrn_mechanism_access_dparam(prop); + _nrn_mechanism_cache_instance _lmc{prop}; + const size_t id = 0; + auto inst = make_instance_heat_eqn_scalar(_lmc); + auto node_data = make_node_data_heat_eqn_scalar(prop); + + } + + + static void _initlists() { + /* X */ + _slist1[0] = {1, 0}; + /* DX */ + _dlist1[0] = {4, 0}; + } + + + /** register channel with the simulator */ + extern "C" void _heat_eqn_scalar_reg() { + _initlists(); + + register_mech(mechanism_info, nrn_alloc_heat_eqn_scalar, nullptr, nrn_jacob_heat_eqn_scalar, nrn_state_heat_eqn_scalar, nrn_init_heat_eqn_scalar, -1, 1); + + mech_type = nrn_get_mechtype(mechanism_info[1]); + hoc_register_parm_default(mech_type, &_parameter_defaults); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"x"} /* 0 */, + _nrn_mechanism_field{"X"} /* 1 */, + _nrn_mechanism_field{"mu"} /* 2 */, + _nrn_mechanism_field{"vol"} /* 3 */, + _nrn_mechanism_field{"DX"} /* 4 */, + _nrn_mechanism_field{"v_unused"} /* 5 */, + _nrn_mechanism_field{"g_unused"} /* 6 */ + ); + + hoc_register_prop_size(mech_type, 7, 0); + hoc_register_ldifus1(_apply_diffusion_function); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + hoc_register_npy_direct(mech_type, npy_direct_func_proc); + } +} diff --git a/longitudinal_diffusion/neuron/heat_eqn_thread_vars.cpp b/longitudinal_diffusion/neuron/heat_eqn_thread_vars.cpp new file mode 100644 index 00000000..426b2fa7 --- /dev/null +++ b/longitudinal_diffusion/neuron/heat_eqn_thread_vars.cpp @@ -0,0 +1,796 @@ +/********************************************************* +Model Name : heat_eqn_thread_vars +Filename : heat_eqn_thread_vars.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include +#include +#include + +/** + * \dir + * \brief Solver for a system of linear equations : Crout matrix decomposition + * + * \file + * \brief Implementation of Crout matrix decomposition (LU decomposition) followed by + * Forward/Backward substitution: Implementation details : (Legacy code) nrn / scopmath / crout.c + */ + +#include +#include + +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +#include "coreneuron/utils/offload.hpp" +#endif + +namespace nmodl { +namespace crout { + +/** + * \brief Crout matrix decomposition : in-place LU Decomposition of matrix a. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: 0 if no error; -1 if matrix is singular or ill-conditioned + */ +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int Crout(int n, T* const a, int* const perm, double* const rowmax) { + // roundoff is the minimal value for a pivot element without its being considered too close to + // zero + double roundoff = 1.e-20; + int i, j, k, r, pivot, irow, save_i = 0, krow; + T sum, equil_1, equil_2; + + /* Initialize permutation and rowmax vectors */ + + for (i = 0; i < n; i++) { + perm[i] = i; + k = 0; + for (j = 1; j < n; j++) { + if (std::fabs(a[i * n + j]) > std::fabs(a[i * n + k])) { + k = j; + } + } + rowmax[i] = a[i * n + k]; + } + + /* Loop over rows and columns r */ + + for (r = 0; r < n; r++) { + /* + * Operate on rth column. This produces the lower triangular matrix + * of terms needed to transform the constant vector. + */ + + for (i = r; i < n; i++) { + sum = 0.0; + irow = perm[i]; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[irow * n + k] * a[krow * n + r]; + } + a[irow * n + r] -= sum; + } + + /* Find row containing the pivot in the rth column */ + + pivot = perm[r]; + equil_1 = std::fabs(a[pivot * n + r] / rowmax[pivot]); + for (i = r + 1; i < n; i++) { + irow = perm[i]; + equil_2 = std::fabs(a[irow * n + r] / rowmax[irow]); + if (equil_2 > equil_1) { + /* make irow the new pivot row */ + + pivot = irow; + save_i = i; + equil_1 = equil_2; + } + } + + /* Interchange entries in permutation vector if necessary */ + + if (pivot != perm[r]) { + perm[save_i] = perm[r]; + perm[r] = pivot; + } + + /* Check that pivot element is not too small */ + + if (std::fabs(a[pivot * n + r]) < roundoff) { + return -1; + } + + /* + * Operate on row in rth position. This produces the upper + * triangular matrix whose diagonal elements are assumed to be unity. + * This matrix is used in the back substitution algorithm. + */ + + for (j = r + 1; j < n; j++) { + sum = 0.0; + for (k = 0; k < r; k++) { + krow = perm[k]; + sum += a[pivot * n + k] * a[krow * n + j]; + } + a[pivot * n + j] = (a[pivot * n + j] - sum) / a[pivot * n + r]; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +/** + * \brief Crout matrix decomposition : Forward/Backward substitution. + * + * Implementation details : (Legacy code) nrn / scopmath / crout.c + * + * Returns: no return variable + */ +#define y_(arg) p[y[arg]] +#define b_(arg) b[arg] +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_acc(routine seq) +nrn_pragma_omp(declare target) +#endif +template +EIGEN_DEVICE_FUNC inline int solveCrout(int n, + T const* const a, + T const* const b, + T* const p, + int const* const perm, + int const* const y = nullptr) { + int i, j, pivot; + T sum; + + /* Perform forward substitution with pivoting */ + if (y) { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (y_(j)); + } + y_(i) -= sum; + } + } else { + for (i = 0; i < n; i++) { + pivot = perm[i]; + sum = 0.0; + for (j = 0; j < i; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] = (b_(pivot) - sum) / a[pivot * n + i]; + } + + /* + * Note that the y vector is already in the correct order for back + * substitution. Perform back substitution, pivoting the matrix but not + * the y vector. There is no need to divide by the diagonal element as + * this is assumed to be unity. + */ + + for (i = n - 1; i >= 0; i--) { + pivot = perm[i]; + sum = 0.0; + for (j = i + 1; j < n; j++) { + sum += a[pivot * n + j] * (p[j]); + } + p[i] -= sum; + } + } + return 0; +} +#if defined(CORENEURON_ENABLE_GPU) && !defined(DISABLE_OPENACC) +nrn_pragma_omp(end declare target) +#endif + +#undef y_ +#undef b_ + +} // namespace crout +} // namespace nmodl + +/** + * \dir + * \brief Newton solver implementations + * + * \file + * \brief Implementation of Newton method for solving system of non-linear equations + */ + +#include +#include + +namespace nmodl { +/// newton solver implementations +namespace newton { + +/** + * @defgroup solver Solver Implementation + * @brief Solver implementation details + * + * Implementation of Newton method for solving system of non-linear equations using Eigen + * - newton::newton_solver with user, e.g. SymPy, provided Jacobian + * + * @{ + */ + +static constexpr int MAX_ITER = 50; +static constexpr double EPS = 1e-13; + +template +EIGEN_DEVICE_FUNC bool is_converged(const Eigen::Matrix& X, + const Eigen::Matrix& J, + const Eigen::Matrix& F, + double eps) { + bool converged = true; + double square_eps = eps * eps; + for (Eigen::Index i = 0; i < N; ++i) { + double square_error = 0.0; + for (Eigen::Index j = 0; j < N; ++j) { + double JX = J(i, j) * X(j); + square_error += JX * JX; + } + + if (F(i) * F(i) > square_eps * square_error) { + converged = false; +// The NVHPC is buggy and wont allow us to short-circuit. +#ifndef __NVCOMPILER + return converged; +#endif + } + } + return converged; +} + +/** + * \brief Newton method with user-provided Jacobian + * + * Newton method with user-provided Jacobian: given initial vector X and a + * functor that calculates `F(X)`, `J(X)` where `J(X)` is the Jacobian of `F(X)`, + * solves for \f$F(X) = 0\f$, starting with initial value of `X` by iterating: + * + * \f[ + * X_{n+1} = X_n - J(X_n)^{-1} F(X_n) + * \f] + * when \f$|F|^2 < eps^2\f$, solution has converged. + * + * @return number of iterations (-1 if failed to converge) + */ +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + // If finite differences are needed, this is stores the stepwidth. + Eigen::Matrix dX; + // Vector to store result of function F(X): + Eigen::Matrix F; + // Matrix to store Jacobian of F(X): + Eigen::Matrix J; + // Solver iteration count: + int iter = -1; + while (++iter < max_iter) { + // calculate F, J from X using user-supplied functor + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // In Eigen the default storage order is ColMajor. + // Crout's implementation requires matrices stored in RowMajor order (C-style arrays). + // Therefore, the transposeInPlace is critical such that the data() method to give the rows + // instead of the columns. + if (!J.IsRowMajor) { + J.transposeInPlace(); + } + Eigen::Matrix pivot; + Eigen::Matrix rowmax; + // Check if J is singular + if (nmodl::crout::Crout(N, J.data(), pivot.data(), rowmax.data()) < 0) { + return -1; + } + Eigen::Matrix X_solve; + nmodl::crout::solveCrout(N, J.data(), F.data(), X_solve.data(), pivot.data()); + X -= X_solve; + } + // If we fail to converge after max_iter iterations, return -1 + return -1; +} + +/** + * Newton method template specializations for \f$N <= 4\f$ Use explicit inverse + * of `F` instead of LU decomposition. This is faster, as there is no pivoting + * and therefore no branches, but it is not numerically safe for \f$N > 4\f$. + */ + +template +EIGEN_DEVICE_FUNC int newton_solver_small_N(Eigen::Matrix& X, + FUNC functor, + double eps, + int max_iter) { + bool invertible; + Eigen::Matrix F; + Eigen::Matrix dX; + Eigen::Matrix J, J_inv; + int iter = -1; + while (++iter < max_iter) { + functor(X, dX, F, J); + if (is_converged(X, J, F, eps)) { + return iter; + } + // The inverse can be called from within OpenACC regions without any issue, as opposed to + // Eigen::PartialPivLU. + J.computeInverseWithCheck(J_inv, invertible); + if (invertible) { + X -= J_inv * F; + } else { + return -1; + } + } + return -1; +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +template +EIGEN_DEVICE_FUNC int newton_solver(Eigen::Matrix& X, + FUNC functor, + double eps = EPS, + int max_iter = MAX_ITER) { + return newton_solver_small_N(X, functor, eps, max_iter); +} + +/** @} */ // end of solver + +} // namespace newton +} // namespace nmodl + + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" +extern void _nrn_thread_reg(int, int, void(*)(Datum*)); + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 0; +static constexpr auto number_of_floating_point_variables = 5; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +Prop* hoc_getdata_range(int type); +extern Node* nrn_alloc_node_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "heat_eqn_thread_vars", + 0, + "x_heat_eqn_thread_vars", + 0, + "X_heat_eqn_thread_vars", + 0, + 0 + }; + + + /* NEURON global variables */ + static neuron::container::field_index _slist1[1], _dlist1[1]; + static int mech_type; + static Prop* _extcall_prop; + /* _prop_id kind of shadows _extcall_prop to allow validity checking. */ + static _nrn_non_owning_id_without_container _prop_id{}; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct heat_eqn_thread_vars_Store { + double thread_data_in_use{0}; + double thread_data[2] /* TODO init const-array */; + double X0{0}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + heat_eqn_thread_vars_Store heat_eqn_thread_vars_global; + auto thread_data_in_use_heat_eqn_thread_vars() -> std::decay::type { + return heat_eqn_thread_vars_global.thread_data_in_use; + } + auto thread_data_heat_eqn_thread_vars() -> std::decay::type { + return heat_eqn_thread_vars_global.thread_data; + } + auto X0_heat_eqn_thread_vars() -> std::decay::type { + return heat_eqn_thread_vars_global.X0; + } + + static std::vector _parameter_defaults = { + }; + + + /** all mechanism instance variables and global variables */ + struct heat_eqn_thread_vars_Instance { + double* x{}; + double* X{}; + double* DX{}; + double* v_unused{}; + double* g_unused{}; + heat_eqn_thread_vars_Store* global{&heat_eqn_thread_vars_global}; + }; + + + struct heat_eqn_thread_vars_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + struct heat_eqn_thread_vars_ThreadVariables { + double * thread_data; + + double * mu_ptr(size_t id) { + return thread_data + 0 + (id % 1); + } + double & mu(size_t id) { + return thread_data[0 + (id % 1)]; + } + double * vol_ptr(size_t id) { + return thread_data + 1 + (id % 1); + } + double & vol(size_t id) { + return thread_data[1 + (id % 1)]; + } + + heat_eqn_thread_vars_ThreadVariables(double * const thread_data) { + this->thread_data = thread_data; + } + }; + + + static heat_eqn_thread_vars_Instance make_instance_heat_eqn_thread_vars(_nrn_mechanism_cache_range& _lmc) { + return heat_eqn_thread_vars_Instance { + _lmc.template fpfield_ptr<0>(), + _lmc.template fpfield_ptr<1>(), + _lmc.template fpfield_ptr<2>(), + _lmc.template fpfield_ptr<3>(), + _lmc.template fpfield_ptr<4>() + }; + } + + + static heat_eqn_thread_vars_NodeData make_node_data_heat_eqn_thread_vars(NrnThread& nt, Memb_list& _ml_arg) { + return heat_eqn_thread_vars_NodeData { + _ml_arg.nodeindices, + nt.node_voltage_storage(), + nt.node_d_storage(), + nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + static heat_eqn_thread_vars_NodeData make_node_data_heat_eqn_thread_vars(Prop * _prop) { + static std::vector node_index{0}; + Node* _node = _nrn_mechanism_access_node(_prop); + return heat_eqn_thread_vars_NodeData { + node_index.data(), + &_nrn_mechanism_access_voltage(_node), + &_nrn_mechanism_access_d(_node), + &_nrn_mechanism_access_rhs(_node), + 1 + }; + } + + void nrn_destructor_heat_eqn_thread_vars(Prop* prop); + + + static void nrn_alloc_heat_eqn_thread_vars(Prop* _prop) { + Datum *_ppvar = nullptr; + _nrn_mechanism_cache_instance _lmc{_prop}; + size_t const _iml = 0; + assert(_nrn_mechanism_get_num_vars(_prop) == 5); + /*initialize range parameters*/ + } + + + /* Mechanism procedures and functions */ + static void* _diffusion_space_X; + static double _diffusion_coefficient_X(int _i, Memb_list* _ml_arg, size_t id, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* /* _thread */, NrnThread* nt, const _nrn_model_sorted_token& _sorted_token) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_thread_vars(_lmc); + auto node_data = make_node_data_heat_eqn_thread_vars(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_thread_vars_ThreadVariables(_thread[0].get()); + *_pdvol= _thread_vars.vol(id); + *_pdfcdc = 0.0; + return _thread_vars.mu(id); + } + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + for(size_t _i = 0; _i < 1; ++_i) { + (*_f)(mech_type, _diffusion_coefficient_X, &_diffusion_space_X, _i, /* x pos */ 1, /* Dx pos */ 2, _sorted_token, _nt); + } + } + + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + _extcall_prop = _prop; + _prop_id = _nrn_get_prop_id(_prop); + } + static void _hoc_setdata() { + Prop *_prop = hoc_getdata_range(mech_type); + _setdata(_prop); + hoc_retpushx(1.); + } + + + struct functor_heat_eqn_thread_vars_0 { + _nrn_mechanism_cache_range& _lmc; + heat_eqn_thread_vars_Instance& inst; + heat_eqn_thread_vars_NodeData& node_data; + size_t id; + Datum* _ppvar; + Datum* _thread; + heat_eqn_thread_vars_ThreadVariables& _thread_vars; + NrnThread* nt; + double v; + double source0_, old_X; + + void initialize() { + ; + source0_ = 0.0; + old_X = inst.X[id]; + } + + functor_heat_eqn_thread_vars_0(_nrn_mechanism_cache_range& _lmc, heat_eqn_thread_vars_Instance& inst, heat_eqn_thread_vars_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, heat_eqn_thread_vars_ThreadVariables& _thread_vars, NrnThread* nt, double v) + : _lmc(_lmc), inst(inst), node_data(node_data), id(id), _ppvar(_ppvar), _thread(_thread), _thread_vars(_thread_vars), nt(nt), v(v) + {} + void operator()(const Eigen::Matrix& nmodl_eigen_xm, Eigen::Matrix& nmodl_eigen_dxm, Eigen::Matrix& nmodl_eigen_fm, Eigen::Matrix& nmodl_eigen_jm) const { + const double* nmodl_eigen_x = nmodl_eigen_xm.data(); + double* nmodl_eigen_dx = nmodl_eigen_dxm.data(); + double* nmodl_eigen_j = nmodl_eigen_jm.data(); + double* nmodl_eigen_f = nmodl_eigen_fm.data(); + nmodl_eigen_dx[0] = std::max(1e-6, 0.02*std::fabs(nmodl_eigen_x[0])); + nmodl_eigen_f[static_cast(0)] = -nmodl_eigen_x[static_cast(0)] / nt->_dt + source0_ / _thread_vars.vol(id) + old_X / nt->_dt; + nmodl_eigen_j[static_cast(0)] = -1.0 / nt->_dt; + } + + void finalize() { + } + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {"mu_heat_eqn_thread_vars", &heat_eqn_thread_vars_global.thread_data[0]}, + {"vol_heat_eqn_thread_vars", &heat_eqn_thread_vars_global.thread_data[1]}, + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {"setdata_heat_eqn_thread_vars", _hoc_setdata}, + {nullptr, nullptr} + }; + static NPyDirectMechFunc npy_direct_func_proc[] = { + {nullptr, nullptr} + }; + static void thread_mem_init(Datum* _thread) { + if(heat_eqn_thread_vars_global.thread_data_in_use) { + _thread[0] = {neuron::container::do_not_search, new double[2]{}}; + } + else { + _thread[0] = {neuron::container::do_not_search, heat_eqn_thread_vars_global.thread_data}; + heat_eqn_thread_vars_global.thread_data_in_use = 1; + } + } + static void thread_mem_cleanup(Datum* _thread) { + double * _thread_data_ptr = _thread[0].get(); + if(_thread_data_ptr == heat_eqn_thread_vars_global.thread_data) { + heat_eqn_thread_vars_global.thread_data_in_use = 0; + } + else { + delete[] _thread_data_ptr; + } + } + + + void nrn_init_heat_eqn_thread_vars(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_thread_vars(_lmc); + auto node_data = make_node_data_heat_eqn_thread_vars(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_thread_vars_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + auto* _ppvar = _ml_arg->pdata[id]; + int node_id = node_data.nodeindices[id]; + auto v = node_data.node_voltages[node_id]; + inst.X[id] = inst.global->X0; + _thread_vars.mu(id) = 1.1; + _thread_vars.vol(id) = 0.01; + if (inst.x[id] < 0.5) { + inst.X[id] = 1.0; + } else { + inst.X[id] = 0.0; + } + } + } + + + void nrn_state_heat_eqn_thread_vars(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_thread_vars(_lmc); + auto node_data = make_node_data_heat_eqn_thread_vars(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_thread_vars_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + + Eigen::Matrix nmodl_eigen_xm; + double* nmodl_eigen_x = nmodl_eigen_xm.data(); + nmodl_eigen_x[static_cast(0)] = inst.X[id]; + // call newton solver + functor_heat_eqn_thread_vars_0 newton_functor(_lmc, inst, node_data, id, _ppvar, _thread, _thread_vars, nt, v); + newton_functor.initialize(); + int newton_iterations = nmodl::newton::newton_solver(nmodl_eigen_xm, newton_functor); + if (newton_iterations < 0) assert(false && "Newton solver did not converge!"); + inst.X[id] = nmodl_eigen_x[static_cast(0)]; + newton_functor.initialize(); // TODO mimic calling F again. + newton_functor.finalize(); + + } + } + + + static void nrn_jacob_heat_eqn_thread_vars(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; + auto inst = make_instance_heat_eqn_thread_vars(_lmc); + auto node_data = make_node_data_heat_eqn_thread_vars(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = heat_eqn_thread_vars_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + int node_id = node_data.nodeindices[id]; + node_data.node_diagonal[node_id] += inst.g_unused[id]; + } + } + void nrn_destructor_heat_eqn_thread_vars(Prop* prop) { + Datum* _ppvar = _nrn_mechanism_access_dparam(prop); + _nrn_mechanism_cache_instance _lmc{prop}; + const size_t id = 0; + auto inst = make_instance_heat_eqn_thread_vars(_lmc); + auto node_data = make_node_data_heat_eqn_thread_vars(prop); + auto _thread_vars = heat_eqn_thread_vars_ThreadVariables(heat_eqn_thread_vars_global.thread_data); + + } + + + static void _initlists() { + /* X */ + _slist1[0] = {1, 0}; + /* DX */ + _dlist1[0] = {2, 0}; + } + + + /** register channel with the simulator */ + extern "C" void _heat_eqn_thread_vars_reg() { + _initlists(); + + register_mech(mechanism_info, nrn_alloc_heat_eqn_thread_vars, nullptr, nrn_jacob_heat_eqn_thread_vars, nrn_state_heat_eqn_thread_vars, nrn_init_heat_eqn_thread_vars, -1, 2); + _extcall_thread.resize(2); + thread_mem_init(_extcall_thread.data()); + heat_eqn_thread_vars_global.thread_data_in_use = 0; + + mech_type = nrn_get_mechtype(mechanism_info[1]); + hoc_register_parm_default(mech_type, &_parameter_defaults); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"x"} /* 0 */, + _nrn_mechanism_field{"X"} /* 1 */, + _nrn_mechanism_field{"DX"} /* 2 */, + _nrn_mechanism_field{"v_unused"} /* 3 */, + _nrn_mechanism_field{"g_unused"} /* 4 */ + ); + + hoc_register_prop_size(mech_type, 5, 0); + hoc_register_ldifus1(_apply_diffusion_function); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + hoc_register_npy_direct(mech_type, npy_direct_func_proc); + _nrn_thread_reg(mech_type, 1, thread_mem_init); + _nrn_thread_reg(mech_type, 0, thread_mem_cleanup); + } +} diff --git a/morphology/neuron/two_radii.cpp b/morphology/neuron/two_radii.cpp index 2432d34c..dea0a83b 100644 --- a/morphology/neuron/two_radii.cpp +++ b/morphology/neuron/two_radii.cpp @@ -164,6 +164,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double square_diam_two_radii(_nrn_mechanism_cache_range& _lmc, two_radii_Instance& inst, two_radii_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double square_area_two_radii(_nrn_mechanism_cache_range& _lmc, two_radii_Instance& inst, two_radii_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -289,11 +292,11 @@ namespace neuron { void nrn_init_two_radii(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_two_radii(_lmc); auto node_data = make_node_data_two_radii(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -313,11 +316,11 @@ namespace neuron { /** update current */ void nrn_cur_two_radii(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_two_radii(_lmc); auto node_data = make_node_data_two_radii(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -333,11 +336,11 @@ namespace neuron { void nrn_state_two_radii(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_two_radii(_lmc); auto node_data = make_node_data_two_radii(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -347,9 +350,10 @@ namespace neuron { static void nrn_jacob_two_radii(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_two_radii(_lmc); auto node_data = make_node_data_two_radii(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/net_event/neuron/receiver.cpp b/net_event/neuron/receiver.cpp index 62020c89..7057042f 100644 --- a/net_event/neuron/receiver.cpp +++ b/net_event/neuron/receiver.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -213,11 +216,11 @@ namespace neuron { void nrn_init_receiver(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_receiver(_lmc); auto node_data = make_node_data_receiver(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -228,9 +231,10 @@ namespace neuron { static void nrn_jacob_receiver(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_receiver(_lmc); auto node_data = make_node_data_receiver(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_event/neuron/spiker.cpp b/net_event/neuron/spiker.cpp index a5bd697c..f0dcdd34 100644 --- a/net_event/neuron/spiker.cpp +++ b/net_event/neuron/spiker.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -213,11 +216,11 @@ namespace neuron { void nrn_init_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_spiker(_lmc); auto node_data = make_node_data_spiker(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -228,9 +231,10 @@ namespace neuron { static void nrn_jacob_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_spiker(_lmc); auto node_data = make_node_data_spiker(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_move/neuron/art_spiker.cpp b/net_move/neuron/art_spiker.cpp index 1e246d47..af53497d 100644 --- a/net_move/neuron/art_spiker.cpp +++ b/net_move/neuron/art_spiker.cpp @@ -161,6 +161,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -216,11 +219,10 @@ namespace neuron { void nrn_init_art_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_spiker(_lmc); - auto node_data = make_node_data_art_spiker(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; inst.y[id] = 0.0; @@ -231,9 +233,9 @@ namespace neuron { static void nrn_jacob_art_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_spiker(_lmc); - auto node_data = make_node_data_art_spiker(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_move/neuron/spiker.cpp b/net_move/neuron/spiker.cpp index a5436dc9..8b7b0d23 100644 --- a/net_move/neuron/spiker.cpp +++ b/net_move/neuron/spiker.cpp @@ -161,6 +161,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -216,11 +219,11 @@ namespace neuron { void nrn_init_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_spiker(_lmc); auto node_data = make_node_data_spiker(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -233,9 +236,10 @@ namespace neuron { static void nrn_jacob_spiker(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_spiker(_lmc); auto node_data = make_node_data_spiker(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_receive/neuron/NetReceiveCalls.cpp b/net_receive/neuron/NetReceiveCalls.cpp index 052ddd48..36a7dd24 100644 --- a/net_receive/neuron/NetReceiveCalls.cpp +++ b/net_receive/neuron/NetReceiveCalls.cpp @@ -163,6 +163,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double one_NetReceiveCalls(_nrn_mechanism_cache_range& _lmc, NetReceiveCalls_Instance& inst, NetReceiveCalls_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int increment_c2_NetReceiveCalls(_nrn_mechanism_cache_range& _lmc, NetReceiveCalls_Instance& inst, NetReceiveCalls_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -279,11 +282,11 @@ namespace neuron { void nrn_init_NetReceiveCalls(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_NetReceiveCalls(_lmc); auto node_data = make_node_data_NetReceiveCalls(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -295,9 +298,10 @@ namespace neuron { static void nrn_jacob_NetReceiveCalls(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_NetReceiveCalls(_lmc); auto node_data = make_node_data_NetReceiveCalls(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_receive/neuron/for_netcons_syn.cpp b/net_receive/neuron/for_netcons_syn.cpp index 7774e851..f2c074d7 100644 --- a/net_receive/neuron/for_netcons_syn.cpp +++ b/net_receive/neuron/for_netcons_syn.cpp @@ -159,6 +159,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -219,11 +222,11 @@ namespace neuron { void nrn_init_ForNetconsSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ForNetconsSyn(_lmc); auto node_data = make_node_data_ForNetconsSyn(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -233,9 +236,10 @@ namespace neuron { static void nrn_jacob_ForNetconsSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ForNetconsSyn(_lmc); auto node_data = make_node_data_ForNetconsSyn(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_receive/neuron/initsyn.cpp b/net_receive/neuron/initsyn.cpp index 8f95df25..d8da37f3 100644 --- a/net_receive/neuron/initsyn.cpp +++ b/net_receive/neuron/initsyn.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -213,11 +216,11 @@ namespace neuron { void nrn_init_InitSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_InitSyn(_lmc); auto node_data = make_node_data_InitSyn(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -227,9 +230,10 @@ namespace neuron { static void nrn_jacob_InitSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_InitSyn(_lmc); auto node_data = make_node_data_InitSyn(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_receive/neuron/snapsyn.cpp b/net_receive/neuron/snapsyn.cpp index 7c6b2fe1..2d72211c 100644 --- a/net_receive/neuron/snapsyn.cpp +++ b/net_receive/neuron/snapsyn.cpp @@ -167,6 +167,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -222,11 +225,11 @@ namespace neuron { void nrn_init_SnapSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_SnapSyn(_lmc); auto node_data = make_node_data_SnapSyn(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -246,11 +249,11 @@ namespace neuron { /** update current */ void nrn_cur_SnapSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_SnapSyn(_lmc); auto node_data = make_node_data_SnapSyn(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -269,11 +272,11 @@ namespace neuron { void nrn_state_SnapSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_SnapSyn(_lmc); auto node_data = make_node_data_SnapSyn(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -283,9 +286,10 @@ namespace neuron { static void nrn_jacob_SnapSyn(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_SnapSyn(_lmc); auto node_data = make_node_data_SnapSyn(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/net_send/neuron/art_toggle.cpp b/net_send/neuron/art_toggle.cpp index dc230328..aafcd1cd 100644 --- a/net_send/neuron/art_toggle.cpp +++ b/net_send/neuron/art_toggle.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -213,11 +216,10 @@ namespace neuron { void nrn_init_art_toggle(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_toggle(_lmc); - auto node_data = make_node_data_art_toggle(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; inst.y[id] = 0.0; @@ -227,9 +229,9 @@ namespace neuron { static void nrn_jacob_art_toggle(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_art_toggle(_lmc); - auto node_data = make_node_data_art_toggle(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/net_send/neuron/toggle.cpp b/net_send/neuron/toggle.cpp index f207eaed..2c8fb29e 100644 --- a/net_send/neuron/toggle.cpp +++ b/net_send/neuron/toggle.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -213,11 +216,11 @@ namespace neuron { void nrn_init_toggle(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_toggle(_lmc); auto node_data = make_node_data_toggle(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -229,9 +232,10 @@ namespace neuron { static void nrn_jacob_toggle(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_toggle(_lmc); auto node_data = make_node_data_toggle(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/neuron_variables/neuron/neuron_variables.cpp b/neuron_variables/neuron/neuron_variables.cpp index e79e82af..2f153405 100644 --- a/neuron_variables/neuron/neuron_variables.cpp +++ b/neuron_variables/neuron/neuron_variables.cpp @@ -151,6 +151,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -190,11 +193,11 @@ namespace neuron { void nrn_init_NeuronVariables(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_NeuronVariables(_lmc); auto node_data = make_node_data_NeuronVariables(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -204,11 +207,11 @@ namespace neuron { void nrn_state_NeuronVariables(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_NeuronVariables(_lmc); auto node_data = make_node_data_NeuronVariables(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -219,9 +222,10 @@ namespace neuron { static void nrn_jacob_NeuronVariables(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_NeuronVariables(_lmc); auto node_data = make_node_data_NeuronVariables(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/nonspecific_current/neuron/leonhard.cpp b/nonspecific_current/neuron/leonhard.cpp index 886cdd58..83468979 100644 --- a/nonspecific_current/neuron/leonhard.cpp +++ b/nonspecific_current/neuron/leonhard.cpp @@ -153,6 +153,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -192,11 +195,11 @@ namespace neuron { void nrn_init_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -215,11 +218,11 @@ namespace neuron { /** update current */ void nrn_cur_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -235,11 +238,11 @@ namespace neuron { void nrn_state_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -249,9 +252,10 @@ namespace neuron { static void nrn_jacob_leonhard(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_leonhard(_lmc); auto node_data = make_node_data_leonhard(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/parameter/neuron/default_parameter.cpp b/parameter/neuron/default_parameter.cpp index 91c9bb66..7d7553a1 100644 --- a/parameter/neuron/default_parameter.cpp +++ b/parameter/neuron/default_parameter.cpp @@ -167,6 +167,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -208,11 +211,11 @@ namespace neuron { void nrn_init_default_parameter(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_default_parameter(_lmc); auto node_data = make_node_data_default_parameter(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -222,9 +225,10 @@ namespace neuron { static void nrn_jacob_default_parameter(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_default_parameter(_lmc); auto node_data = make_node_data_default_parameter(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/parameter/neuron/limits.cpp b/parameter/neuron/limits.cpp index cc06c4f7..3d8bbd31 100644 --- a/parameter/neuron/limits.cpp +++ b/parameter/neuron/limits.cpp @@ -168,6 +168,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -213,11 +216,11 @@ namespace neuron { void nrn_init_limits_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_limits_mod(_lmc); auto node_data = make_node_data_limits_mod(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -227,9 +230,10 @@ namespace neuron { static void nrn_jacob_limits_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_limits_mod(_lmc); auto node_data = make_node_data_limits_mod(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/parameter/neuron/range_parameter.cpp b/parameter/neuron/range_parameter.cpp index e382901d..e34eb820 100644 --- a/parameter/neuron/range_parameter.cpp +++ b/parameter/neuron/range_parameter.cpp @@ -163,6 +163,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -218,11 +221,11 @@ namespace neuron { void nrn_init_range_parameter(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_range_parameter(_lmc); auto node_data = make_node_data_range_parameter(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -233,9 +236,10 @@ namespace neuron { static void nrn_jacob_range_parameter(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_range_parameter(_lmc); auto node_data = make_node_data_range_parameter(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/point_process/neuron/pp.cpp b/point_process/neuron/pp.cpp index 2c35f8e4..cf82f497 100644 --- a/point_process/neuron/pp.cpp +++ b/point_process/neuron/pp.cpp @@ -153,6 +153,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -208,11 +211,11 @@ namespace neuron { void nrn_init_pp(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pp(_lmc); auto node_data = make_node_data_pp(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -222,9 +225,10 @@ namespace neuron { static void nrn_jacob_pp(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pp(_lmc); auto node_data = make_node_data_pp(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/pointer/neuron/basic_pointer.cpp b/pointer/neuron/basic_pointer.cpp index 3b569124..e3317b24 100644 --- a/pointer/neuron/basic_pointer.cpp +++ b/pointer/neuron/basic_pointer.cpp @@ -172,6 +172,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double read_p1_basic_pointer(_nrn_mechanism_cache_range& _lmc, basic_pointer_Instance& inst, basic_pointer_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double read_p2_basic_pointer(_nrn_mechanism_cache_range& _lmc, basic_pointer_Instance& inst, basic_pointer_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -303,11 +306,11 @@ namespace neuron { void nrn_init_basic_pointer(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_basic_pointer(_lmc); auto node_data = make_node_data_basic_pointer(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -321,9 +324,10 @@ namespace neuron { static void nrn_jacob_basic_pointer(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_basic_pointer(_lmc); auto node_data = make_node_data_basic_pointer(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/pointer/neuron/point_basic.cpp b/pointer/neuron/point_basic.cpp index 058775be..71bfeee5 100644 --- a/pointer/neuron/point_basic.cpp +++ b/pointer/neuron/point_basic.cpp @@ -179,6 +179,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double read_p1_point_basic(_nrn_mechanism_cache_range& _lmc, point_basic_Instance& inst, point_basic_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double read_p2_point_basic(_nrn_mechanism_cache_range& _lmc, point_basic_Instance& inst, point_basic_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -294,11 +297,11 @@ namespace neuron { void nrn_init_point_basic(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_basic(_lmc); auto node_data = make_node_data_point_basic(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -312,9 +315,10 @@ namespace neuron { static void nrn_jacob_point_basic(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_basic(_lmc); auto node_data = make_node_data_point_basic(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/pointer/neuron/pointing.cpp b/pointer/neuron/pointing.cpp index c51437b4..407c7736 100644 --- a/pointer/neuron/pointing.cpp +++ b/pointer/neuron/pointing.cpp @@ -150,6 +150,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double is_valid_pointing(_nrn_mechanism_cache_range& _lmc, pointing_Instance& inst, pointing_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -236,11 +239,11 @@ namespace neuron { void nrn_init_pointing(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pointing(_lmc); auto node_data = make_node_data_pointing(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -250,9 +253,10 @@ namespace neuron { static void nrn_jacob_pointing(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pointing(_lmc); auto node_data = make_node_data_pointing(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/procedure/neuron/point_procedures.cpp b/procedure/neuron/point_procedures.cpp index 42666f07..ff60f334 100644 --- a/procedure/neuron/point_procedures.cpp +++ b/procedure/neuron/point_procedures.cpp @@ -163,6 +163,9 @@ namespace neuron { inline int set_x_v_point_procedures(_nrn_mechanism_cache_range& _lmc, point_procedures_Instance& inst, point_procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int set_x_just_v_point_procedures(_nrn_mechanism_cache_range& _lmc, point_procedures_Instance& inst, point_procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int set_x_just_vv_point_procedures(_nrn_mechanism_cache_range& _lmc, point_procedures_Instance& inst, point_procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -435,11 +438,11 @@ namespace neuron { void nrn_init_point_procedures(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_procedures(_lmc); auto node_data = make_node_data_point_procedures(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -450,9 +453,10 @@ namespace neuron { static void nrn_jacob_point_procedures(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_procedures(_lmc); auto node_data = make_node_data_point_procedures(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/procedure/neuron/procedures.cpp b/procedure/neuron/procedures.cpp index 0465c166..48da1e24 100644 --- a/procedure/neuron/procedures.cpp +++ b/procedure/neuron/procedures.cpp @@ -153,6 +153,9 @@ namespace neuron { inline int set_x_v_procedures(_nrn_mechanism_cache_range& _lmc, procedures_Instance& inst, procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int set_x_just_v_procedures(_nrn_mechanism_cache_range& _lmc, procedures_Instance& inst, procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int set_x_just_vv_procedures(_nrn_mechanism_cache_range& _lmc, procedures_Instance& inst, procedures_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -524,11 +527,11 @@ namespace neuron { void nrn_init_procedures(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_procedures(_lmc); auto node_data = make_node_data_procedures(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -539,9 +542,10 @@ namespace neuron { static void nrn_jacob_procedures(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_procedures(_lmc); auto node_data = make_node_data_procedures(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/random/neuron/random_variable.cpp b/random/neuron/random_variable.cpp index 12c6aab6..9bc5a885 100644 --- a/random/neuron/random_variable.cpp +++ b/random/neuron/random_variable.cpp @@ -150,6 +150,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double negexp_random_variable(_nrn_mechanism_cache_range& _lmc, random_variable_Instance& inst, random_variable_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -232,11 +235,11 @@ namespace neuron { void nrn_init_random_variable(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_random_variable(_lmc); auto node_data = make_node_data_random_variable(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -246,9 +249,10 @@ namespace neuron { static void nrn_jacob_random_variable(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_random_variable(_lmc); auto node_data = make_node_data_random_variable(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/solve/neuron/cnexp_array.cpp b/solve/neuron/cnexp_array.cpp index fef45db3..7a34c95a 100644 --- a/solve/neuron/cnexp_array.cpp +++ b/solve/neuron/cnexp_array.cpp @@ -168,6 +168,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -207,11 +210,11 @@ namespace neuron { void nrn_init_cnexp_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_array(_lmc); auto node_data = make_node_data_cnexp_array(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -230,11 +233,11 @@ namespace neuron { void nrn_state_cnexp_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_array(_lmc); auto node_data = make_node_data_cnexp_array(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -245,9 +248,10 @@ namespace neuron { static void nrn_jacob_cnexp_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_array(_lmc); auto node_data = make_node_data_cnexp_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/solve/neuron/cnexp_scalar.cpp b/solve/neuron/cnexp_scalar.cpp index 15d38250..ef238e01 100644 --- a/solve/neuron/cnexp_scalar.cpp +++ b/solve/neuron/cnexp_scalar.cpp @@ -156,6 +156,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -195,11 +198,11 @@ namespace neuron { void nrn_init_cnexp_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_scalar(_lmc); auto node_data = make_node_data_cnexp_scalar(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -211,11 +214,11 @@ namespace neuron { void nrn_state_cnexp_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_scalar(_lmc); auto node_data = make_node_data_cnexp_scalar(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -226,9 +229,10 @@ namespace neuron { static void nrn_jacob_cnexp_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_cnexp_scalar(_lmc); auto node_data = make_node_data_cnexp_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/solve/neuron/derivimplicit_array.cpp b/solve/neuron/derivimplicit_array.cpp index 7cefd5be..9a8a183d 100644 --- a/solve/neuron/derivimplicit_array.cpp +++ b/solve/neuron/derivimplicit_array.cpp @@ -552,6 +552,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -624,11 +627,11 @@ namespace neuron { void nrn_init_derivimplicit_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_array(_lmc); auto node_data = make_node_data_derivimplicit_array(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -647,11 +650,11 @@ namespace neuron { void nrn_state_derivimplicit_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_array(_lmc); auto node_data = make_node_data_derivimplicit_array(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -674,9 +677,10 @@ namespace neuron { static void nrn_jacob_derivimplicit_array(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_array(_lmc); auto node_data = make_node_data_derivimplicit_array(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/solve/neuron/derivimplicit_scalar.cpp b/solve/neuron/derivimplicit_scalar.cpp index 165ff130..00aa3fb6 100644 --- a/solve/neuron/derivimplicit_scalar.cpp +++ b/solve/neuron/derivimplicit_scalar.cpp @@ -540,6 +540,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -612,11 +615,11 @@ namespace neuron { void nrn_init_derivimplicit_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_scalar(_lmc); auto node_data = make_node_data_derivimplicit_scalar(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -628,11 +631,11 @@ namespace neuron { void nrn_state_derivimplicit_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_scalar(_lmc); auto node_data = make_node_data_derivimplicit_scalar(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -655,9 +658,10 @@ namespace neuron { static void nrn_jacob_derivimplicit_scalar(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_derivimplicit_scalar(_lmc); auto node_data = make_node_data_derivimplicit_scalar(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/solve/neuron/finite_difference.cpp b/solve/neuron/finite_difference.cpp index e9405102..29a1002a 100644 --- a/solve/neuron/finite_difference.cpp +++ b/solve/neuron/finite_difference.cpp @@ -566,6 +566,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double f_finite_difference(_nrn_mechanism_cache_range& _lmc, finite_difference_Instance& inst, finite_difference_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, finite_difference_ThreadVariables& _thread_vars, NrnThread* nt, double _lx); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -703,12 +706,12 @@ namespace neuron { void nrn_init_finite_difference(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_finite_difference(_lmc); auto node_data = make_node_data_finite_difference(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = finite_difference_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -721,12 +724,12 @@ namespace neuron { void nrn_state_finite_difference(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_finite_difference(_lmc); auto node_data = make_node_data_finite_difference(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; auto _thread_vars = finite_difference_ThreadVariables(_thread[0].get()); + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -749,9 +752,11 @@ namespace neuron { static void nrn_jacob_finite_difference(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_finite_difference(_lmc); auto node_data = make_node_data_finite_difference(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; + auto _thread_vars = finite_difference_ThreadVariables(_thread[0].get()); auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/spike_travel/neuron/expsyn2.cpp b/spike_travel/neuron/expsyn2.cpp index 58bfeae1..13a200d8 100644 --- a/spike_travel/neuron/expsyn2.cpp +++ b/spike_travel/neuron/expsyn2.cpp @@ -181,6 +181,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -236,11 +239,11 @@ namespace neuron { void nrn_init_ExpSyn2(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ExpSyn2(_lmc); auto node_data = make_node_data_ExpSyn2(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -261,11 +264,11 @@ namespace neuron { /** update current */ void nrn_cur_ExpSyn2(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ExpSyn2(_lmc); auto node_data = make_node_data_ExpSyn2(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -284,11 +287,11 @@ namespace neuron { void nrn_state_ExpSyn2(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ExpSyn2(_lmc); auto node_data = make_node_data_ExpSyn2(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -299,9 +302,10 @@ namespace neuron { static void nrn_jacob_ExpSyn2(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ExpSyn2(_lmc); auto node_data = make_node_data_ExpSyn2(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/spike_travel/neuron/hodhux.cpp b/spike_travel/neuron/hodhux.cpp index 432cbbca..b35363b2 100644 --- a/spike_travel/neuron/hodhux.cpp +++ b/spike_travel/neuron/hodhux.cpp @@ -257,6 +257,9 @@ namespace neuron { inline double vtrap_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx, double _ly); inline int states_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline int rates_hodhux(_nrn_mechanism_cache_range& _lmc, hodhux_Instance& inst, hodhux_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -459,11 +462,11 @@ namespace neuron { void nrn_init_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -495,11 +498,11 @@ namespace neuron { /** update current */ void nrn_cur_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -523,11 +526,11 @@ namespace neuron { void nrn_state_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -543,9 +546,10 @@ namespace neuron { static void nrn_jacob_hodhux(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_hodhux(_lmc); auto node_data = make_node_data_hodhux(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/state/neuron/default_values.cpp b/state/neuron/default_values.cpp index 386ade3c..40aacb77 100644 --- a/state/neuron/default_values.cpp +++ b/state/neuron/default_values.cpp @@ -189,6 +189,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -232,11 +235,11 @@ namespace neuron { void nrn_init_default_values(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_default_values(_lmc); auto node_data = make_node_data_default_values(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -256,9 +259,10 @@ namespace neuron { static void nrn_jacob_default_values(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_default_values(_lmc); auto node_data = make_node_data_default_values(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/steady_state/neuron/minipump.cpp b/steady_state/neuron/minipump.cpp index 3abcedfb..917dfc7a 100644 --- a/steady_state/neuron/minipump.cpp +++ b/steady_state/neuron/minipump.cpp @@ -582,6 +582,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -724,11 +727,11 @@ namespace neuron { void nrn_init_minipump(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_minipump(_lmc); auto node_data = make_node_data_minipump(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -767,11 +770,11 @@ namespace neuron { void nrn_state_minipump(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_minipump(_lmc); auto node_data = make_node_data_minipump(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -798,9 +801,10 @@ namespace neuron { static void nrn_jacob_minipump(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_minipump(_lmc); auto node_data = make_node_data_minipump(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/suffix/neuron/no_suffix.cpp b/suffix/neuron/no_suffix.cpp index c8248d2f..0009cdad 100644 --- a/suffix/neuron/no_suffix.cpp +++ b/suffix/neuron/no_suffix.cpp @@ -146,6 +146,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -185,11 +188,11 @@ namespace neuron { void nrn_init_no_suffix(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_no_suffix(_lmc); auto node_data = make_node_data_no_suffix(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -200,9 +203,10 @@ namespace neuron { static void nrn_jacob_no_suffix(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_no_suffix(_lmc); auto node_data = make_node_data_no_suffix(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/suffix/neuron/point_suffix.cpp b/suffix/neuron/point_suffix.cpp index 298e0757..6a207470 100644 --- a/suffix/neuron/point_suffix.cpp +++ b/suffix/neuron/point_suffix.cpp @@ -156,6 +156,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -211,11 +214,11 @@ namespace neuron { void nrn_init_point_suffix(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_suffix(_lmc); auto node_data = make_node_data_point_suffix(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -226,9 +229,10 @@ namespace neuron { static void nrn_jacob_point_suffix(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_point_suffix(_lmc); auto node_data = make_node_data_point_suffix(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/table/neuron/table.cpp b/table/neuron/table.cpp index eeb83d68..7ff9238f 100644 --- a/table/neuron/table.cpp +++ b/table/neuron/table.cpp @@ -224,6 +224,9 @@ namespace neuron { inline double quadratic_tbl(_nrn_mechanism_cache_range& _lmc, tbl_Instance& inst, tbl_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx); inline int sigmoidal_tbl(_nrn_mechanism_cache_range& _lmc, tbl_Instance& inst, tbl_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); inline int sinusoidal_tbl(_nrn_mechanism_cache_range& _lmc, tbl_Instance& inst, tbl_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -578,11 +581,11 @@ namespace neuron { void nrn_init_tbl(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl(_lmc); auto node_data = make_node_data_tbl(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -603,11 +606,11 @@ namespace neuron { /** update current */ void nrn_cur_tbl(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl(_lmc); auto node_data = make_node_data_tbl(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -623,11 +626,11 @@ namespace neuron { void nrn_state_tbl(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl(_lmc); auto node_data = make_node_data_tbl(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -637,9 +640,10 @@ namespace neuron { static void nrn_jacob_tbl(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl(_lmc); auto node_data = make_node_data_tbl(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/table/neuron/table_point_process.cpp b/table/neuron/table_point_process.cpp index be99084e..7d41c8fa 100644 --- a/table/neuron/table_point_process.cpp +++ b/table/neuron/table_point_process.cpp @@ -234,6 +234,9 @@ namespace neuron { inline double quadratic_tbl_point_process(_nrn_mechanism_cache_range& _lmc, tbl_point_process_Instance& inst, tbl_point_process_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx); inline int sigmoidal_tbl_point_process(_nrn_mechanism_cache_range& _lmc, tbl_point_process_Instance& inst, tbl_point_process_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lv); inline int sinusoidal_tbl_point_process(_nrn_mechanism_cache_range& _lmc, tbl_point_process_Instance& inst, tbl_point_process_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt, double _lx); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Point Process specific functions */ static void* _hoc_create_pnt(Object* _ho) { return create_point_process(_pointtype, _ho); @@ -557,11 +560,11 @@ namespace neuron { void nrn_init_tbl_point_process(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl_point_process(_lmc); auto node_data = make_node_data_tbl_point_process(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -582,11 +585,11 @@ namespace neuron { /** update current */ void nrn_cur_tbl_point_process(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl_point_process(_lmc); auto node_data = make_node_data_tbl_point_process(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; double v = node_data.node_voltages[node_id]; @@ -605,11 +608,11 @@ namespace neuron { void nrn_state_tbl_point_process(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl_point_process(_lmc); auto node_data = make_node_data_tbl_point_process(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -619,9 +622,10 @@ namespace neuron { static void nrn_jacob_tbl_point_process(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_tbl_point_process(_lmc); auto node_data = make_node_data_tbl_point_process(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/useion/neuron/ionic.cpp b/useion/neuron/ionic.cpp index c135e32a..d0c688ab 100644 --- a/useion/neuron/ionic.cpp +++ b/useion/neuron/ionic.cpp @@ -162,6 +162,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -201,11 +204,11 @@ namespace neuron { void nrn_init_ionic(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ionic(_lmc); auto node_data = make_node_data_ionic(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -217,11 +220,11 @@ namespace neuron { void nrn_state_ionic(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ionic(_lmc); auto node_data = make_node_data_ionic(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; auto* _ppvar = _ml_arg->pdata[id]; @@ -234,9 +237,10 @@ namespace neuron { static void nrn_jacob_ionic(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_ionic(_lmc); auto node_data = make_node_data_ionic(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { int node_id = node_data.nodeindices[id]; diff --git a/useion/neuron/read_cai.cpp b/useion/neuron/read_cai.cpp index 6290d4e6..e5409b4b 100644 --- a/useion/neuron/read_cai.cpp +++ b/useion/neuron/read_cai.cpp @@ -161,6 +161,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -200,11 +203,11 @@ namespace neuron { void nrn_init_read_cai(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_cai(_lmc); auto node_data = make_node_data_read_cai(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -216,9 +219,10 @@ namespace neuron { static void nrn_jacob_read_cai(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_cai(_lmc); auto node_data = make_node_data_read_cai(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/read_cao.cpp b/useion/neuron/read_cao.cpp index 09457e7b..a3b1590e 100644 --- a/useion/neuron/read_cao.cpp +++ b/useion/neuron/read_cao.cpp @@ -161,6 +161,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -200,11 +203,11 @@ namespace neuron { void nrn_init_read_cao(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_cao(_lmc); auto node_data = make_node_data_read_cao(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -216,9 +219,10 @@ namespace neuron { static void nrn_jacob_read_cao(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_cao(_lmc); auto node_data = make_node_data_read_cao(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/read_eca.cpp b/useion/neuron/read_eca.cpp index 988e6eb3..f5bbfee0 100644 --- a/useion/neuron/read_eca.cpp +++ b/useion/neuron/read_eca.cpp @@ -158,6 +158,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -197,11 +200,11 @@ namespace neuron { void nrn_init_read_eca(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_eca(_lmc); auto node_data = make_node_data_read_eca(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -213,9 +216,10 @@ namespace neuron { static void nrn_jacob_read_eca(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_read_eca(_lmc); auto node_data = make_node_data_read_eca(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/style_ion.cpp b/useion/neuron/style_ion.cpp index 83474dd8..cc3cd695 100644 --- a/useion/neuron/style_ion.cpp +++ b/useion/neuron/style_ion.cpp @@ -180,6 +180,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -219,11 +222,11 @@ namespace neuron { void nrn_init_style_ion(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_style_ion(_lmc); auto node_data = make_node_data_style_ion(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -240,9 +243,10 @@ namespace neuron { static void nrn_jacob_style_ion(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_style_ion(_lmc); auto node_data = make_node_data_style_ion(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/valence.cpp b/useion/neuron/valence.cpp index f0b5fd12..b3e33b05 100644 --- a/useion/neuron/valence.cpp +++ b/useion/neuron/valence.cpp @@ -161,6 +161,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -200,11 +203,11 @@ namespace neuron { void nrn_init_valence_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_valence_mod(_lmc); auto node_data = make_node_data_valence_mod(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -216,9 +219,10 @@ namespace neuron { static void nrn_jacob_valence_mod(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_valence_mod(_lmc); auto node_data = make_node_data_valence_mod(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/write_cai.cpp b/useion/neuron/write_cai.cpp index 05500614..81415d91 100644 --- a/useion/neuron/write_cai.cpp +++ b/useion/neuron/write_cai.cpp @@ -163,6 +163,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -202,11 +205,11 @@ namespace neuron { void nrn_init_write_cai(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_cai(_lmc); auto node_data = make_node_data_write_cai(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -221,9 +224,10 @@ namespace neuron { static void nrn_jacob_write_cai(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_cai(_lmc); auto node_data = make_node_data_write_cai(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/write_cao.cpp b/useion/neuron/write_cao.cpp index 5140b6e2..53c50a49 100644 --- a/useion/neuron/write_cao.cpp +++ b/useion/neuron/write_cao.cpp @@ -163,6 +163,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -202,11 +205,11 @@ namespace neuron { void nrn_init_write_cao(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_cao(_lmc); auto node_data = make_node_data_write_cao(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -221,9 +224,10 @@ namespace neuron { static void nrn_jacob_write_cao(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_cao(_lmc); auto node_data = make_node_data_write_cao(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/useion/neuron/write_eca.cpp b/useion/neuron/write_eca.cpp index f1c7c89d..0b58bf1b 100644 --- a/useion/neuron/write_eca.cpp +++ b/useion/neuron/write_eca.cpp @@ -155,6 +155,9 @@ namespace neuron { /* Mechanism procedures and functions */ + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -194,11 +197,11 @@ namespace neuron { void nrn_init_write_eca(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_eca(_lmc); auto node_data = make_node_data_write_eca(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -210,9 +213,10 @@ namespace neuron { static void nrn_jacob_write_eca(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_write_eca(_lmc); auto node_data = make_node_data_write_eca(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/verbatim/neuron/globals.cpp b/verbatim/neuron/globals.cpp index 9b55ff91..dff77450 100644 --- a/verbatim/neuron/globals.cpp +++ b/verbatim/neuron/globals.cpp @@ -149,6 +149,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double get_gbl_globals(_nrn_mechanism_cache_range& _lmc, globals_Instance& inst, globals_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -246,11 +249,11 @@ namespace neuron { void nrn_init_globals(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_globals(_lmc); auto node_data = make_node_data_globals(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -260,9 +263,10 @@ namespace neuron { static void nrn_jacob_globals(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_globals(_lmc); auto node_data = make_node_data_globals(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/verbatim/neuron/internal_function.cpp b/verbatim/neuron/internal_function.cpp index fb6bd1a0..704a2822 100644 --- a/verbatim/neuron/internal_function.cpp +++ b/verbatim/neuron/internal_function.cpp @@ -145,6 +145,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double f_internal_function(_nrn_mechanism_cache_range& _lmc, internal_function_Instance& inst, internal_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); inline double g_internal_function(_nrn_mechanism_cache_range& _lmc, internal_function_Instance& inst, internal_function_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -282,11 +285,11 @@ namespace neuron { void nrn_init_internal_function(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_internal_function(_lmc); auto node_data = make_node_data_internal_function(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -296,9 +299,10 @@ namespace neuron { static void nrn_jacob_internal_function(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_internal_function(_lmc); auto node_data = make_node_data_internal_function(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { } diff --git a/verbatim/neuron/pointer_in_double.cpp b/verbatim/neuron/pointer_in_double.cpp index 677f9289..6180b26e 100644 --- a/verbatim/neuron/pointer_in_double.cpp +++ b/verbatim/neuron/pointer_in_double.cpp @@ -146,6 +146,9 @@ namespace neuron { /* Mechanism procedures and functions */ inline double use_pointer_pointer_in_double(_nrn_mechanism_cache_range& _lmc, pointer_in_double_Instance& inst, pointer_in_double_NodeData& node_data, size_t id, Datum* _ppvar, Datum* _thread, NrnThread* nt); + static void _apply_diffusion_function(ldifusfunc2_t _f, const _nrn_model_sorted_token& _sorted_token, NrnThread& _nt) { + } + /* Neuron setdata functions */ extern void _nrn_setdata_reg(int, void(*)(Prop*)); static void _setdata(Prop* _prop) { @@ -265,11 +268,11 @@ namespace neuron { void nrn_init_pointer_in_double(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pointer_in_double(_lmc); auto node_data = make_node_data_pointer_in_double(*nt, *_ml_arg); - auto nodecount = _ml_arg->nodecount; auto* _thread = _ml_arg->_thread; + auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { auto* _ppvar = _ml_arg->pdata[id]; int node_id = node_data.nodeindices[id]; @@ -292,9 +295,10 @@ namespace neuron { static void nrn_jacob_pointer_in_double(const _nrn_model_sorted_token& _sorted_token, NrnThread* nt, Memb_list* _ml_arg, int _type) { - _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _type}; + _nrn_mechanism_cache_range _lmc{_sorted_token, *nt, *_ml_arg, _ml_arg->type()}; auto inst = make_instance_pointer_in_double(_lmc); auto node_data = make_node_data_pointer_in_double(*nt, *_ml_arg); + auto* _thread = _ml_arg->_thread; auto nodecount = _ml_arg->nodecount; for (int id = 0; id < nodecount; id++) { }