NEURON
eion.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/nrnoc/eion.cpp,v 1.10 1998/02/26 16:42:50 hines Exp */
3 
4 #include <cstdlib>
5 #include "cabcode.h"
6 #include "section.h"
7 #include "neuron.h"
9 #include "membfunc.h"
10 #include "parse.hpp"
11 #include "membdef.h"
12 #include "nrniv_mf.h"
13 #include "nrnunits.h"
14 
15 #include <array>
16 #include <string>
17 
18 #include <map>
19 #include <set>
20 
21 #undef hoc_retpushx
22 
23 
24 static constexpr auto nparm = 5;
25 static constexpr auto ndparam = 1;
26 static const char* mechanism[] = {/*just a template*/
27  "0",
28  "na_ion",
29  "ena",
30  "nao",
31  "nai",
32  0,
33  "ina",
34  "dina_dv_",
35  0,
36  0};
37 static DoubScal scdoub[] = {/* just a template*/
38  {"ci0_na_ion", 0},
39  {"co0_na_ion", 0},
40  {0, 0}};
41 
42 static void ion_alloc(Prop*);
43 
44 static void ion_cur(neuron::model_sorted_token const&, NrnThread*, Memb_list*, int);
45 
46 static void ion_init(neuron::model_sorted_token const&, NrnThread*, Memb_list*, int);
47 
48 static int na_ion, k_ion, ca_ion; /* will get type for these special ions */
49 
50 int nrn_is_ion(int type) {
51  return (memb_func[type].alloc == ion_alloc);
52 }
53 
55 static double** ion_global_map;
56 #define global_conci(type) ion_global_map[type][0]
57 #define global_conco(type) ion_global_map[type][1]
58 #define global_charge(type) ion_global_map[type][2]
59 
60 double nrn_ion_charge(Symbol* sym) {
61  return global_charge(sym->subtype);
62 }
63 
64 void ion_register(void) {
65  /* hoc level registration of ion name. Return -1 if name already
66  in use and not an ion; and the mechanism subtype otherwise.
67  */
68  char* name;
69  Symbol* s;
70  Symlist* sav;
71  int fail;
72  fail = 0;
73  sav = hoc_symlist;
75  name = gargstr(1);
76  auto const buf_size = strlen(name) + 10;
77  char* const buf = static_cast<char*>(emalloc(buf_size));
78  std::snprintf(buf, buf_size, "%s_ion", name);
79  s = hoc_lookup(buf);
80  if (s && s->type == MECHANISM && memb_func[s->subtype].alloc == ion_alloc) {
81  hoc_symlist = sav;
82  free(buf);
83  if (*getarg(2) != global_charge(s->subtype)) {
84  hoc_execerr_ext("%s already defined with charge %g, cannot redefine with charge %g",
85  s->name,
86  global_charge(s->subtype),
87  *getarg(2));
88  }
89  hoc_retpushx((double) s->subtype);
90  return;
91  }
92  if (s) {
93  fail = 1;
94  }
95  std::snprintf(buf, buf_size, "e%s", name);
96  if (hoc_lookup(buf)) {
97  fail = 1;
98  }
99  std::snprintf(buf, buf_size, "%si", name);
100  if (hoc_lookup(buf)) {
101  fail = 1;
102  }
103  std::snprintf(buf, buf_size, "%so", name);
104  if (hoc_lookup(buf)) {
105  fail = 1;
106  }
107  std::snprintf(buf, buf_size, "i%s", name);
108  if (hoc_lookup(buf)) {
109  fail = 1;
110  }
111  std::snprintf(buf, buf_size, "di%s_dv_", name);
112  if (hoc_lookup(buf)) {
113  fail = 1;
114  }
115  if (fail) {
116  hoc_symlist = sav;
117  free(buf);
118  hoc_retpushx(-1.);
119  return;
120  }
121  double charge = *getarg(2);
123  if (strcmp(name, "ca") == 0 && charge != 2.0) {
124  // In the very rare edge case that ca is not yet defined
125  // define with charge 2.0
126  ion_reg(name, 2.0);
127  // and emit a recoverable error as above to avoid an exit in ion_reg
128  free(buf);
129  hoc_execerr_ext("ca_ion already defined with charge 2, cannot redefine with charge %g\n",
130  charge);
131  }
132  ion_reg(name, charge);
133  hoc_symlist = sav;
134  std::snprintf(buf, buf_size, "%s_ion", name);
135  s = hoc_lookup(buf);
136  hoc_retpushx((double) s->subtype);
137  free(buf);
138 }
139 
140 void ion_charge(void) {
141  Symbol* s;
142  s = hoc_lookup(gargstr(1));
143  if (!s || s->type != MECHANISM || memb_func[s->subtype].alloc != ion_alloc) {
144  hoc_execerror(gargstr(1), "is not an ion mechanism");
145  }
146  hoc_retpushx(global_charge(s->subtype));
147 }
148 
149 static std::vector<double> naparmdflt{DEF_ena, DEF_nai, DEF_nao};
150 static std::vector<double> kparmdflt{DEF_ek, DEF_ki, DEF_ko};
151 static std::vector<double> caparmdflt{DEF_eca, DEF_cai, DEF_cao};
152 static std::vector<double> ionparmdflt{DEF_eion, DEF_ioni, DEF_iono};
153 
154 void reg_parm_default(int mechtype, const std::string& name) {
155  if (name == "na") {
157  } else {
159  }
160 }
161 
162 void ion_reg(const char* name, double valence) {
163  int i, mechtype;
164  Symbol* s;
165  double val;
166  std::array<std::string, 7> buf{};
167  std::string name_s{name};
168 #define VAL_SENTINAL -10000.
169  buf[0] = name_s + "_ion";
170  buf[1] = "e" + name_s;
171  buf[2] = name_s + "i";
172  buf[3] = name_s + "o";
173  buf[5] = "i" + name_s;
174  buf[6] = "di" + name_s + "_dv_";
175  for (i = 0; i < 7; i++) {
176  mechanism[i + 1] = buf[i].c_str();
177  }
178  mechanism[5] = nullptr; /* buf[4] not used above */
179  s = hoc_lookup(buf[0].c_str());
180  if (!s || s->type != MECHANISM || memb_func[s->subtype].alloc != ion_alloc) {
181  register_mech(mechanism, ion_alloc, ion_cur, nullptr, nullptr, ion_init, -1, 1);
182  hoc_symbol_limits(hoc_lookup(buf[2].c_str()), 1e-12, 1e9);
183  hoc_symbol_limits(hoc_lookup(buf[3].c_str()), 1e-12, 1e9);
184  hoc_symbol_units(hoc_lookup(buf[1].c_str()), "mV");
185  hoc_symbol_units(hoc_lookup(buf[2].c_str()), "mM");
186  hoc_symbol_units(hoc_lookup(buf[3].c_str()), "mM");
187  hoc_symbol_units(hoc_lookup(buf[5].c_str()), "mA/cm2");
188  hoc_symbol_units(hoc_lookup(buf[6].c_str()), "S/cm2");
189  s = hoc_lookup(buf[0].c_str());
190  mechtype = nrn_get_mechtype(mechanism[1]);
191  reg_parm_default(mechtype, name_s);
194  field<double>{buf[1]}, // erev
195  field<double>{buf[2]}, // conci
196  field<double>{buf[3]}, // conco
197  field<double>{buf[5]}, // cur
198  field<double>{buf[6]}, // dcurdv
199  field<int>{"iontype", "iontype"});
201  hoc_register_dparam_semantics(mechtype, 0, "iontype");
202  nrn_writes_conc(mechtype, 1);
203  if (ion_global_map_size <= s->subtype) {
204  ion_global_map_size = s->subtype + 1;
206  sizeof(double*) * ion_global_map_size);
207  }
208  ion_global_map[s->subtype] = (double*) emalloc(3 * sizeof(double));
209  buf[0] = name_s + "i0_" + s->name;
210  scdoub[0].name = buf[0].c_str();
211  scdoub[0].pdoub = ion_global_map[s->subtype];
212  buf[1] = name_s + "o0_" + s->name;
213  scdoub[1].name = buf[1].c_str();
214  scdoub[1].pdoub = ion_global_map[s->subtype] + 1;
218  if (strcmp("na", name) == 0) {
219  na_ion = s->subtype;
220  global_conci(s->subtype) = DEF_nai;
221  global_conco(s->subtype) = DEF_nao;
222  global_charge(s->subtype) = 1.;
223  } else if (strcmp("k", name) == 0) {
224  k_ion = s->subtype;
225  global_conci(s->subtype) = DEF_ki;
226  global_conco(s->subtype) = DEF_ko;
227  global_charge(s->subtype) = 1.;
228  } else if (strcmp("ca", name) == 0) {
229  ca_ion = s->subtype;
230  global_conci(s->subtype) = DEF_cai;
231  global_conco(s->subtype) = DEF_cao;
232  global_charge(s->subtype) = 2.;
233  } else {
234  global_conci(s->subtype) = DEF_ioni;
235  global_conco(s->subtype) = DEF_iono;
236  global_charge(s->subtype) = VAL_SENTINAL;
237  }
238  for (i = 0; i < 3; ++i) { /* used to be nrnocCONST */
239  s->u.ppsym[i]->subtype = _AMBIGUOUS;
240  }
241  }
242  val = global_charge(s->subtype);
243  if (valence != VAL_SENTINAL && val != VAL_SENTINAL && valence != val) {
244  fprintf(stderr,
245  "%s ion charge defined differently in\n\
246 two USEION statements (%g and %g)\n",
247  s->name,
248  valence,
249  global_charge(s->subtype));
250  nrn_exit(1);
251  } else if (valence == VAL_SENTINAL && val == VAL_SENTINAL) {
252  /* Not defined now but could be defined by
253  a subsequent ion_reg from another model.
254  The list of ion mechanisms will be checked
255  after all mod files have been dealt with to verify
256  that they all have a defined valence.
257  */
258  } else if (valence != VAL_SENTINAL) {
259  global_charge(s->subtype) = valence;
260  }
261 }
262 
264  int i;
265  for (i = 3; i < n_memb_func; ++i)
266  if (nrn_is_ion(i)) {
267  if (global_charge(i) == VAL_SENTINAL) {
268  Symbol* s = memb_func[i].sym;
269  Fprintf(stderr,
270  "%s USEION CHARGE (or VALENCE) must be defined in\n\
271 at least one model using this ion\n",
272  s->name);
273  nrn_exit(1);
274  }
275  }
276 }
277 
278 #define ktf (1000. * _gasconstant_codata2018 * (celsius + 273.15) / _faraday_codata2018)
279 double nrn_nernst(double ci, double co, double z) {
280  /*printf("nrn_nernst %g %g %g\n", ci, co, z);*/
281  if (z == 0) {
282  return 0.;
283  }
284  if (ci <= 0.) {
285  return 1e6;
286  } else if (co <= 0.) {
287  return -1e6;
288  } else {
289  return ktf / z * log(co / ci);
290  }
291 }
292 
293 void nrn_wrote_conc(Symbol* sym, double& erev, double ci, double co, int it) {
294  if (it & 040) {
295  erev = nrn_nernst(ci, co, nrn_ion_charge(sym));
296  }
297 }
298 
299 void nernst(void) {
300  double val = 0.0;
301 
302  if (hoc_is_str_arg(1)) {
303  Symbol* s = hoc_lookup(gargstr(1));
304  if (s && ion_global_map[s->u.rng.type]) {
305  Section* sec = chk_access();
306  Symbol* ion = memb_func[s->u.rng.type].sym;
307  double z = global_charge(s->u.rng.type);
308  double x;
309  if (ifarg(2)) {
310  x = chkarg(2, 0., 1.);
311  } else {
312  x = .5;
313  }
314  auto ci = nrn_rangepointer(sec, ion->u.ppsym[1], x);
315  auto co = nrn_rangepointer(sec, ion->u.ppsym[2], x);
316  auto e = nrn_rangepointer(sec, ion->u.ppsym[0], x);
317  switch (s->u.rng.index) {
318  case 0:
319  val = nrn_nernst(*ci, *co, z);
320  hoc_retpushx(val);
321  return;
322  case 1:
323  val = *co * exp(-z / ktf * *e);
324  hoc_retpushx(val);
325  return;
326  case 2:
327  val = *ci * exp(z / ktf * *e);
328  hoc_retpushx(val);
329  return;
330  }
331  }
332  hoc_execerror(gargstr(1), " not a reversal potential or concentration");
333  } else {
334  val = nrn_nernst(*getarg(1), *getarg(2), *getarg(3));
335  /*printf("nernst=%g\n", val);*/
336  }
337  hoc_retpushx(val);
338  return;
339 }
340 
341 static double efun(double x) {
342  if (fabs(x) < 1e-4) {
343  return 1. - x / 2.;
344  } else {
345  return x / (exp(x) - 1);
346  }
347 }
348 
349 double nrn_ghk(double v, double ci, double co, double z) {
350  double eco, eci, temp;
351  temp = z * v / ktf;
352  eco = co * efun(temp);
353  eci = ci * efun(-temp);
354  return (.001) * z * _faraday_codata2018 * (eci - eco);
355 }
356 
357 void ghk(void) {
358  double val = nrn_ghk(*getarg(1), *getarg(2), *getarg(3), *getarg(4));
359  hoc_retpushx(val);
360 }
361 
362 static constexpr auto iontype_index_dparam = 0;
363 static constexpr auto erev_index = 0; /* From Eion */
364 static constexpr auto conci_index = 1;
365 static constexpr auto conco_index = 2;
366 static constexpr auto cur_index = 3;
367 static constexpr auto dcurdv_index = 4;
368 
369 /*
370  handle erev, conci, conc0 "in the right way" according to ion_style
371  default. See nrn/lib/help/nrnoc.help.
372 ion_style("name_ion", [c_style, e_style, einit, eadvance, cinit])
373 
374  ica is assigned
375  eca is parameter but if conc exists then eca is assigned
376  if conc is nrnocCONST then eca calculated on finitialize
377  if conc is STATE then eca calculated on fadvance and conc finitialize
378  with global nai0, nao0
379 
380  nernst(ci, co, charge) and ghk(v, ci, co, charge) available to hoc
381  and models.
382 */
383 
384 #define charge global_charge(type)
385 #define conci0 global_conci(type)
386 #define conco0 global_conco(type)
387 
388 double nrn_nernst_coef(int type) {
389  /* for computing jacobian element dconc'/dconc */
390  return ktf / charge;
391 }
392 
393 /*
394 It is generally an error for two models to WRITE the same concentration.
395 
396 nrn_check_conc_write checks that there's no write conflict; and warns if it
397 detects one. It also sets respective write flag in the style of the ion.
398 
399 The argument `i` specifies which concentration is being written to. It's 0 for
400 exterior; and 1 for interior.
401 */
402 
403 // Each mechanism type index that writes a concentration has a set of ion
404 // type indices it writes to.
405 // ionconctype is coded as iontype*2 + i where i=1 for interior
406 // So number of distinct ion mechanisms is essentially unlimited, max_int/2.
407 static std::map<int, std::set<int>> mechtype2ionconctype;
408 
409 static void add_mechtype2ionconctype(int mechtype, int iontype, int i) {
410  auto& set_of_ionconctypes = mechtype2ionconctype[mechtype];
411  set_of_ionconctypes.insert(2 * iontype + i); // unique though inserting for each instance.
412 }
413 
414 static bool mech_uses_ionconctype(int mechtype, int iontype, int i) {
415  if (auto search = mechtype2ionconctype.find(mechtype); search != mechtype2ionconctype.end()) {
416  auto& set_of_ionconctypes = search->second;
417  return set_of_ionconctypes.count(2 * iontype + i) == 1;
418  }
419  return false;
420 }
421 
422 void nrn_check_conc_write(Prop* pmech, Prop* pion, int i) {
423  // Would be less redundant to generate the "database" at
424  // mechanism registration time. But NMODL presently gives us this info
425  // only at each mechanism instance allocation.
426  add_mechtype2ionconctype(pmech->_type, pion->_type, i);
427 
428  Prop* p;
429  int flag;
430  if (i == 1) {
431  flag = 0200;
432  } else {
433  flag = 0400;
434  }
435 
436  auto ii = pion->dparam[iontype_index_dparam].get<int>();
437  if (ii & flag) {
438  // Is the possibility in fact actual. Unfortunately, uninserting the
439  // mechanism that writes a concentration does not reset the flag bit.
440  // So search the node property list for another mechanism that also
441  // writes this ion concentration. (that is needed anyway to
442  // fill out the warning message.)
443 
444  // the pion in the node property list is before mechanisms that use the ion
445  for (p = pion->next; p; p = p->next) {
446  if (p == pmech) {
447  continue;
448  }
449  if (mech_uses_ionconctype(p->_type, pion->_type, i)) {
450  char buf[300];
451  Sprintf(buf,
452  "%.*s%c is being written at the same location by %s and %s",
453  (int) strlen(memb_func[pion->_type].sym->name) - 4,
454  memb_func[pion->_type].sym->name,
455  ((i == 1) ? 'i' : 'o'),
456  memb_func[pmech->_type].sym->name,
457  memb_func[p->_type].sym->name);
458  hoc_warning(buf, (char*) 0);
459  }
460  }
461  }
462  ii |= flag;
463  pion->dparam[iontype_index_dparam] = ii;
464 }
465 
466 void ion_style(void) {
467  Symbol* s;
468  int istyle, i, oldstyle;
469  Section* sec;
470  Prop* p;
471 
472  s = hoc_lookup(gargstr(1));
473  if (!s || s->type != MECHANISM || !nrn_is_ion(s->subtype)) {
474  hoc_execerror(gargstr(1), " is not an ion");
475  }
476 
477  sec = chk_access();
478  p = nrn_mechanism(s->subtype, sec->pnode[0]);
479  oldstyle = -1;
480  if (p) {
481  oldstyle = p->dparam[iontype_index_dparam].get<int>();
482  }
483 
484  if (ifarg(2)) {
485  istyle = (int) chkarg(2, 0., 3.); /* c_style */
486  istyle += 010 * (int) chkarg(3, 0., 3.); /* e_style */
487  istyle += 040 * (int) chkarg(4, 0., 1.); /* einit */
488  istyle += 0100 * (int) chkarg(5, 0., 1.); /* eadvance */
489  istyle += 04 * (int) chkarg(6, 0., 1.); /* cinit*/
490  for (i = 0; i < sec->nnode; ++i) {
491  p = nrn_mechanism(s->subtype, sec->pnode[i]);
492  if (p) {
493  auto ii = p->dparam[iontype_index_dparam].get<int>();
494  ii &= (0200 + 0400);
495  ii += istyle;
496  p->dparam[iontype_index_dparam] = ii;
497  }
498  }
499  }
500  hoc_retpushx((double) oldstyle);
501 }
502 
503 int nrn_vartype(const Symbol* sym) {
504  int i;
505  i = sym->subtype;
506  if (i == _AMBIGUOUS) {
507  Section* sec;
508  Prop* p;
509  sec = nrn_noerr_access();
510  if (!sec) {
511  return nrnocCONST;
512  }
513  p = nrn_mechanism(sym->u.rng.type, sec->pnode[0]);
514  if (p) {
515  auto it = p->dparam[iontype_index_dparam].get<int>();
516  if (sym->u.rng.index == 0) { /* erev */
517  i = (it & 030) >> 3; /* unused, nrnocCONST, DEP, or STATE */
518  } else { /* concentration */
519  i = (it & 03);
520  }
521  }
522  }
523  return i;
524 }
525 
526 /* the ion mechanism it flag defines how _AMBIGUOUS is to be interpreted */
527 void nrn_promote(Prop* p, int conc, int rev) {
528  int it = p->dparam[iontype_index_dparam].get<int>();
529  int oldconc = (it & 03);
530  int oldrev = (it & 030) >> 3;
531  /* precedence */
532  if (oldconc < conc) {
533  oldconc = conc;
534  }
535  if (oldrev < rev) {
536  oldrev = rev;
537  }
538  /* promote type */
539  if (oldconc > 0 && oldrev < 2) {
540  oldrev = 2;
541  }
542  it &= ~0177; /* clear the bitmap */
543  it += oldconc + 010 * oldrev;
544  if (oldconc == 3) { /* if state then cinit */
545  it += 4;
546  if (oldrev == 2) { /* if not state (WRITE) then eadvance */
547  it += 0100;
548  }
549  }
550  if (oldconc > 0 && oldrev == 2) { /*einit*/
551  it += 040;
552  }
553  p->dparam[iontype_index_dparam] = it; // this sets iontype to 8
554 }
555 
556 /*the bitmap is
557  03 concentration unused, nrnocCONST, DEP, STATE
558  04 initialize concentrations
559  030 reversal potential unused, nrnocCONST, DEP, STATE
560  040 initialize reversal potential
561 0100 calc reversal during fadvance
562 0200 ci being written by a model
563 0400 co being written by a model
564 */
565 
566 /* Must be called prior to any channels which update the currents */
567 static void ion_cur(neuron::model_sorted_token const& sorted_token,
568  NrnThread* nt,
569  Memb_list* ml,
570  int type) {
571  neuron::cache::MechanismRange<nparm, ndparam> ml_cache{sorted_token, *nt, *ml, type};
572  auto const count = ml->nodecount;
573  /*printf("ion_cur %s\n", memb_func[type].sym->name);*/
574  for (int i = 0; i < count; ++i) {
575  ml_cache.fpfield<dcurdv_index>(i) = 0.0;
576  ml_cache.fpfield<cur_index>(i) = 0.0;
577  auto const iontype = ml->pdata[i][iontype_index_dparam].get<int>();
578  if (iontype & 0100) {
579  ml_cache.fpfield<erev_index>(i) = nrn_nernst(ml_cache.fpfield<conci_index>(i),
580  ml_cache.fpfield<conco_index>(i),
581  charge);
582  }
583  };
584 }
585 
586 /* Must be called prior to other models which possibly also initialize
587  concentrations based on their own states
588 */
589 static void ion_init(neuron::model_sorted_token const& sorted_token,
590  NrnThread* nt,
591  Memb_list* ml,
592  int type) {
593  int i;
594  neuron::cache::MechanismRange<nparm, ndparam> ml_cache{sorted_token, *nt, *ml, type};
595  int count = ml->nodecount;
596  /*printf("ion_init %s\n", memb_func[type].sym->name);*/
597  for (i = 0; i < count; ++i) {
598  auto const iontype = ml->pdata[i][iontype_index_dparam].get<int>();
599  if (iontype & 04) {
600  ml_cache.fpfield<conci_index>(i) = conci0;
601  ml_cache.fpfield<conco_index>(i) = conco0;
602  }
603  }
604  for (i = 0; i < count; ++i) {
605  auto const iontype = ml->pdata[i][iontype_index_dparam].get<int>();
606  if (iontype & 040) {
607  ml_cache.fpfield<erev_index>(i) = nrn_nernst(ml_cache.fpfield<conci_index>(i),
608  ml_cache.fpfield<conco_index>(i),
609  charge);
610  }
611  }
612 }
613 
614 static void ion_alloc(Prop* p) {
615  assert(p->param_size() == nparm);
616  assert(p->param_num_vars() == nparm);
617  p->param(cur_index) = 0.;
618  p->param(dcurdv_index) = 0.;
619  if (p->_type == na_ion) {
620  p->param(erev_index) = naparmdflt[0];
621  p->param(conci_index) = naparmdflt[1];
622  p->param(conco_index) = naparmdflt[2];
623  } else if (p->_type == k_ion) {
624  p->param(erev_index) = kparmdflt[0];
625  p->param(conci_index) = kparmdflt[1];
626  p->param(conco_index) = kparmdflt[2];
627  } else if (p->_type == ca_ion) {
628  p->param(erev_index) = caparmdflt[0];
629  p->param(conci_index) = caparmdflt[1];
630  p->param(conco_index) = caparmdflt[2];
631  } else {
632  p->param(erev_index) = ionparmdflt[0];
633  p->param(conci_index) = ionparmdflt[1];
634  p->param(conco_index) = ionparmdflt[2];
635  }
636  p->dparam = nrn_prop_datum_alloc(p->_type, ndparam, p);
637  p->dparam[iontype_index_dparam] = 0;
638 }
639 
641  extern int secondorder;
642  NrnThreadMembList* tml;
643  Memb_list* ml;
644  int i, i2;
645  constexpr auto c = 3;
646  constexpr auto dc = 4;
647  if (secondorder == 2) {
648  for (tml = nt->tml; tml; tml = tml->next)
649  if (memb_func[tml->index].alloc == ion_alloc) {
650  ml = tml->ml;
651  i2 = ml->nodecount;
652  for (i = 0; i < i2; ++i) {
653  ml->data(i, c) += ml->data(i, dc) * (NODERHS(ml->nodelist[i]));
654  }
655  }
656  }
657 }
Section * chk_access()
Definition: cabcode.cpp:449
Prop * nrn_mechanism(int type, Node *nd)
Definition: cabcode.cpp:1038
Section * nrn_noerr_access(void)
return 0 if no accessed section
Definition: cabcode.cpp:474
neuron::container::data_handle< double > nrn_rangepointer(Section *sec, Symbol *s, double d)
Definition: cabcode.cpp:1274
char * gargstr(int narg)
Definition: code2.cpp:227
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
Datum * nrn_prop_datum_alloc(int type, int count, Prop *p)
Definition: cxprop.cpp:33
double chkarg(int, double low, double high)
Definition: code2.cpp:626
char buf[512]
Definition: init.cpp:13
void hoc_execerr_ext(const char *fmt,...)
printf style specification of hoc_execerror message.
Definition: fileio.cpp:828
int hoc_is_str_arg(int narg)
Definition: code.cpp:872
void hoc_retpushx(double x)
Definition: hocusr.cpp:154
void hoc_symbol_limits(Symbol *sym, float low, float high)
Definition: code2.cpp:102
Symbol * hoc_lookup(const char *)
Definition: symbol.cpp:59
static int c
Definition: hoc.cpp:169
#define assert(ex)
Definition: hocassrt.h:24
#define getarg
Definition: hocdec.h:17
Symlist * hoc_top_level_symlist
Definition: code2.cpp:677
char * hoc_symbol_units(Symbol *, const char *)
Definition: code2.cpp:128
#define _AMBIGUOUS
Definition: membfunc.hpp:86
#define nrnocCONST
Definition: membfunc.hpp:63
#define DEF_nai
#define DEF_eion
#define DEF_eca
#define DEF_ek
#define DEF_nao
#define DEF_ioni
#define DEF_iono
#define DEF_ko
#define DEF_cao
#define DEF_cai
#define DEF_ki
#define DEF_ena
exp
Definition: extdef.h:5
log
Definition: extdef.h:4
fabs
Definition: extdef.h:3
const char * name
Definition: init.cpp:16
long subtype
Definition: init.cpp:107
void nrn_exit(int err)
Definition: nrnoc_aux.cpp:30
void nrn_writes_conc(int, int)
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
void hoc_register_dparam_semantics(int type, int, const char *name)
void hoc_register_var(DoubScal *ds, DoubVec *dv, VoidFunc *)
Definition: global_vars.cpp:31
void * erealloc(void *ptr, size_t size)
Definition: nrnoc_aux.cpp:94
static void * emalloc(size_t size)
Definition: mpispike.cpp:30
int nrn_get_mechtype(const char *name)
Get mechanism type by the mechanism name.
Definition: mk_mech.cpp:145
void hoc_register_prop_size(int, int, int)
int register_mech(const char **m, mod_alloc_t alloc, mod_f_t cur, mod_f_t jacob, mod_f_t stat, mod_f_t initialize, mod_f_t private_constructor, mod_f_t private_destructor, int nrnpointerindex, int vectorized)
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
static void register_data_fields(int mech_type, Fields const &... fields)
Type- and array-aware version of hoc_register_prop_size.
Definition: membfunc.h:235
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
int ii
Definition: cellorder.cpp:631
int iontype(char *s1, char *s2)
Definition: nocpout.cpp:2054
size_t p
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
static bool mech_uses_ionconctype(int mechtype, int iontype, int i)
Definition: eion.cpp:414
static double ** ion_global_map
Definition: eion.cpp:55
void ghk(void)
Definition: eion.cpp:357
static constexpr auto erev_index
Definition: eion.cpp:363
static constexpr auto cur_index
Definition: eion.cpp:366
double nrn_ion_charge(Symbol *sym)
Definition: eion.cpp:60
void nrn_verify_ion_charge_defined()
Definition: eion.cpp:263
static std::vector< double > kparmdflt
Definition: eion.cpp:150
void nernst(void)
Definition: eion.cpp:299
static std::vector< double > naparmdflt
Definition: eion.cpp:149
void second_order_cur(NrnThread *nt)
Definition: eion.cpp:640
#define global_conco(type)
Definition: eion.cpp:57
static int na_ion
Definition: eion.cpp:48
static constexpr auto ndparam
Definition: eion.cpp:25
static DoubScal scdoub[]
Definition: eion.cpp:37
int nrn_vartype(const Symbol *sym)
Definition: eion.cpp:503
void ion_charge(void)
Definition: eion.cpp:140
static double efun(double x)
Definition: eion.cpp:341
#define VAL_SENTINAL
static constexpr auto iontype_index_dparam
Definition: eion.cpp:362
void nrn_promote(Prop *p, int conc, int rev)
Definition: eion.cpp:527
static int k_ion
Definition: eion.cpp:48
#define ktf
Definition: eion.cpp:278
void nrn_wrote_conc(Symbol *sym, double &erev, double ci, double co, int it)
Definition: eion.cpp:293
static int ion_global_map_size
Definition: eion.cpp:54
static constexpr auto conci_index
Definition: eion.cpp:364
int nrn_is_ion(int type)
Definition: eion.cpp:50
static void ion_cur(neuron::model_sorted_token const &, NrnThread *, Memb_list *, int)
Definition: eion.cpp:567
static std::vector< double > ionparmdflt
Definition: eion.cpp:152
static void add_mechtype2ionconctype(int mechtype, int iontype, int i)
Definition: eion.cpp:409
#define conci0
Definition: eion.cpp:385
static std::vector< double > caparmdflt
Definition: eion.cpp:151
#define global_charge(type)
Definition: eion.cpp:58
double nrn_ghk(double v, double ci, double co, double z)
Definition: eion.cpp:349
void ion_style(void)
Definition: eion.cpp:466
void ion_register(void)
Definition: eion.cpp:64
static int ca_ion
Definition: eion.cpp:48
static constexpr auto nparm
Definition: eion.cpp:24
void nrn_check_conc_write(Prop *pmech, Prop *pion, int i)
Definition: eion.cpp:422
static constexpr auto conco_index
Definition: eion.cpp:365
static void ion_alloc(Prop *)
Definition: eion.cpp:614
static std::map< int, std::set< int > > mechtype2ionconctype
Definition: eion.cpp:407
double nrn_nernst(double ci, double co, double z)
Definition: eion.cpp:279
static constexpr auto dcurdv_index
Definition: eion.cpp:367
double nrn_nernst_coef(int type)
Definition: eion.cpp:388
static const char * mechanism[]
Definition: eion.cpp:26
void ion_reg(const char *name, double valence)
Definition: eion.cpp:162
static void ion_init(neuron::model_sorted_token const &, NrnThread *, Memb_list *, int)
Definition: eion.cpp:589
#define charge
Definition: eion.cpp:384
#define conco0
Definition: eion.cpp:386
#define global_conci(type)
Definition: eion.cpp:56
void reg_parm_default(int mechtype, const std::string &name)
Definition: eion.cpp:154
void hoc_register_parm_default(int mechtype, const std::vector< double > *pd)
Definition: init.cpp:741
int n_memb_func
Definition: init.cpp:448
constexpr double _faraday_codata2018
Definition: nrnunits.h:20
Symlist * hoc_symlist
Definition: symbol.cpp:34
#define NODERHS(n)
Definition: section_fwd.hpp:55
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:28
double * pdoub
Definition: hocdec.h:197
const char * name
Definition: hocdec.h:196
A view into a set of mechanism instances.
Definition: nrnoc_ml.h:34
int nodecount
Definition: nrnoc_ml.h:78
Node ** nodelist
Definition: nrnoc_ml.h:68
Datum ** pdata
Definition: nrnoc_ml.h:75
std::vector< double * > data()
Get a vector of double* representing the model data.
Definition: memblist.cpp:64
Represent main neuron object computed by single thread.
Definition: multicore.h:58
NrnThreadMembList * tml
Definition: multicore.h:62
struct NrnThreadMembList * next
Definition: multicore.h:34
Memb_list * ml
Definition: multicore.h:35
Definition: section.h:231
Datum * dparam
Definition: section.h:247
short _type
Definition: section.h:244
Prop * next
Definition: section.h:243
Definition: model.h:47
union Symbol::@28 u
Symbol ** ppsym
Definition: hocdec.h:125
struct Symbol::@45::@46 rng
long subtype
Definition: model.h:49
Definition: hocdec.h:75
Version of Memb_list for use in performance-critical code.
T get() const
Explicit conversion to any T.
int Fprintf(FILE *stream, const char *fmt, Args... args)
Definition: logger.hpp:8