NEURON
register_mech.cpp
Go to the documentation of this file.
1 /*
2 # =============================================================================
3 # Copyright (c) 2016 - 2021 Blue Brain Project/EPFL
4 #
5 # See top-level LICENSE file for details.
6 # =============================================================================.
7 */
8 
9 #include <cstring>
10 
11 #include "coreneuron/nrnconf.h"
12 #include "nrnoc/ion_semantics.h"
20 
21 namespace coreneuron {
22 int secondorder = 0;
23 double t, dt, celsius, pi;
24 int rev_dt;
25 
26 using Pfrv = void (*)();
27 
28 static void ion_write_depend(int type, int etype);
29 
31  if (type == -1) {
32  return;
33  }
35 }
37  if (type == -1) {
38  return;
39  }
41 }
42 
44  if (type == -1) {
45  return;
46  }
47  corenrn.get_has_net_event().push_back(type);
48 }
49 
50 /* values are type numbers of mechanisms which have FOR_NETCONS statement */
51 int nrn_fornetcon_cnt_; /* how many models have a FOR_NETCONS statement */
52 int* nrn_fornetcon_type_; /* what are the type numbers */
53 int* nrn_fornetcon_index_; /* what is the index into the ppvar array */
54 
55 void add_nrn_fornetcons(int type, int indx) {
56  if (type == -1)
57  return;
58 
59  int i = nrn_fornetcon_cnt_++;
60  nrn_fornetcon_type_ = (int*) erealloc(nrn_fornetcon_type_, (i + 1) * sizeof(int));
61  nrn_fornetcon_index_ = (int*) erealloc(nrn_fornetcon_index_, (i + 1) * sizeof(int));
64 }
65 
66 void add_nrn_artcell(int type, int qi) {
67  if (type == -1) {
68  return;
69  }
70 
73 }
74 
78  short size) {
79  if (type == -1) {
80  return;
81  }
85 }
86 
94  corenrn.get_is_artificial().resize(memb_func_size_, false);
102 }
103 
104 void initnrn() {
105  secondorder = DEF_secondorder; /* >0 means crank-nicolson. 2 means currents
106  adjusted to t+dt/2 */
107  t = 0.; /* msec */
108  dt = DEF_dt; /* msec */
109  rev_dt = (int) (DEF_rev_dt); /* 1/msec */
110  celsius = DEF_celsius; /* degrees celsius */
111 }
112 
113 /* if vectorized then thread_data_size added to it */
114 int register_mech(const char** m,
115  mod_alloc_t alloc,
116  mod_f_t cur,
117  mod_f_t jacob,
118  mod_f_t stat,
119  mod_f_t initialize,
120  mod_f_t private_constructor,
121  mod_f_t private_destructor,
122  int /* nrnpointerindex */,
123  int vectorized) {
124  auto& memb_func = corenrn.get_memb_funcs();
125 
126  int type = nrn_get_mechtype(m[1]);
127 
128  // No mechanism in the .dat files
129  if (type == -1)
130  return type;
131 
132  assert(type);
133 #ifdef DEBUG
134  printf("register_mech %s %d\n", m[1], type);
135 #endif
136  if (memb_func[type].sym) {
137  assert(strcmp(memb_func[type].sym, m[1]) == 0);
138  } else {
139  memb_func[type].sym = (char*) emalloc(strlen(m[1]) + 1);
140  strcpy(memb_func[type].sym, m[1]);
141  }
142  memb_func[type].current = cur;
143  memb_func[type].jacob = jacob;
144  memb_func[type].alloc = alloc;
145  memb_func[type].state = stat;
146  memb_func[type].initialize = initialize;
147  memb_func[type].constructor = nullptr;
148  memb_func[type].destructor = nullptr;
149  memb_func[type].private_constructor = private_constructor;
150  memb_func[type].private_destructor = private_destructor;
151 #if VECTORIZE
152  memb_func[type].vectorized = vectorized ? 1 : 0;
153  memb_func[type].thread_size_ = vectorized ? (vectorized - 1) : 0;
154  memb_func[type].thread_mem_init_ = nullptr;
155  memb_func[type].thread_cleanup_ = nullptr;
156  memb_func[type].thread_table_check_ = nullptr;
157  memb_func[type].is_point = 0;
158  memb_func[type].setdata_ = nullptr;
159  memb_func[type].dparam_semantics = nullptr;
160 #endif
162  return type;
163 }
164 
165 void nrn_writes_conc(int type, int /* unused */) {
166  static int lastion = EXTRACELL + 1;
167  if (type == -1)
168  return;
169 
170 #if CORENRN_DEBUG
171  printf("%s reordered from %d to %d\n", corenrn.get_memb_func(type).sym, type, lastion);
172 #endif
173  if (nrn_is_ion(type)) {
174  ++lastion;
175  }
176 }
177 
178 void _nrn_layout_reg(int type, int layout) {
179  corenrn.get_mech_data_layout()[type] = layout;
180 }
181 
183  corenrn.get_net_buf_receive().emplace_back(f, type);
184 }
185 
187  corenrn.get_net_buf_send_type().push_back(type);
188 }
189 
191  corenrn.get_watch_check()[type] = nwc;
192 }
193 
194 void hoc_register_prop_size(int type, int psize, int dpsize) {
195  if (type == -1)
196  return;
197 
198  int pold = corenrn.get_prop_param_size()[type];
199  int dpold = corenrn.get_prop_dparam_size()[type];
200  if (psize != pold || dpsize != dpold) {
202  }
203  corenrn.get_prop_param_size()[type] = psize;
204  corenrn.get_prop_dparam_size()[type] = dpsize;
205  if (dpsize) {
206  corenrn.get_memb_func(type).dparam_semantics = (int*) ecalloc(dpsize, sizeof(int));
207  }
208 }
209 void hoc_register_dparam_semantics(int type, int ix, const char* name) {
210  /* needed for SoA to possibly reorder name_ion and some "pointer" pointers. */
211  /* only interested in area, iontype, cvode_ieq,
212  netsend, pointer, pntproc, bbcorepointer, watch, diam, fornetcon
213  xx_ion and #xx_ion which will get
214  a semantics value of -1, -2, -3,
215  -4, -5, -6, -7, -8, -9, -10,
216  2*type, and 2*type+1 respectively
217  */
218  auto& memb_func = corenrn.get_memb_funcs();
219  if (strcmp(name, "area") == 0) {
220  memb_func[type].dparam_semantics[ix] = -1;
221  } else if (strcmp(name, "iontype") == 0) {
222  memb_func[type].dparam_semantics[ix] = -2;
223  } else if (strcmp(name, "cvodeieq") == 0) {
224  memb_func[type].dparam_semantics[ix] = -3;
225  } else if (strcmp(name, "netsend") == 0) {
226  memb_func[type].dparam_semantics[ix] = -4;
227  } else if (strcmp(name, "pointer") == 0) {
228  memb_func[type].dparam_semantics[ix] = -5;
229  } else if (strcmp(name, "pntproc") == 0) {
230  memb_func[type].dparam_semantics[ix] = -6;
231  } else if (strcmp(name, "bbcorepointer") == 0) {
232  memb_func[type].dparam_semantics[ix] = -7;
233  } else if (strcmp(name, "watch") == 0) {
234  memb_func[type].dparam_semantics[ix] = -8;
235  } else if (strcmp(name, "diam") == 0) {
236  memb_func[type].dparam_semantics[ix] = -9;
237  } else if (strcmp(name, "fornetcon") == 0) {
238  memb_func[type].dparam_semantics[ix] = -10;
239  } else if (strcmp(name, "random") == 0) {
240  memb_func[type].dparam_semantics[ix] = -11;
241  } else {
242  int i = name[0] == '#' ? 1 : 0;
243  int etype = nrn_get_mechtype(name + i);
244  memb_func[type].dparam_semantics[ix] = nrn_semantics_from_ion(etype, i);
245  /* note that if style is needed (i==1), then we are writing a concentration */
246  if (i) {
247  ion_write_depend(type, etype);
248  }
249  }
250 #if CORENRN_DEBUG
251  printf("dparam semantics %s ix=%d %s %d\n",
252  memb_func[type].sym,
253  ix,
254  name,
255  memb_func[type].dparam_semantics[ix]);
256 #endif
257 }
258 
259 /* only ion type ion_write_depend_ are non-nullptr */
260 /* and those are array of integers with first integer being array size */
261 /* and remaining size-1 integers containing the mechanism types that write concentrations to that
262  * ion */
263 static void ion_write_depend(int type, int etype) {
264  auto& memb_func = corenrn.get_memb_funcs();
265  auto& ion_write_depend_ = corenrn.get_ion_write_dependency();
266  if (ion_write_depend_.size() < memb_func.size()) {
267  ion_write_depend_.resize(memb_func.size());
268  }
269 
270  int size = !ion_write_depend_[etype].empty() ? ion_write_depend_[etype][0] + 1 : 2;
271 
272  ion_write_depend_[etype].resize(size, 0);
273  ion_write_depend_[etype][0] = size;
274  ion_write_depend_[etype][size - 1] = type;
275 }
276 
277 static int depend_append(int idep, int* dependencies, int deptype, int type) {
278  /* append only if not already in dependencies and != type*/
279  bool add = true;
280  if (deptype == type) {
281  return idep;
282  }
283  for (int i = 0; i < idep; ++i) {
284  if (deptype == dependencies[i]) {
285  add = false;
286  break;
287  }
288  }
289  if (add) {
290  dependencies[idep++] = deptype;
291  }
292  return idep;
293 }
294 
295 /* return list of types that this type depends on (10 should be more than enough) */
296 /* dependencies must be an array that is large enough to hold that array */
297 /* number of dependencies is returned */
298 int nrn_mech_depend(int type, int* dependencies) {
299  int dpsize = corenrn.get_prop_dparam_size()[type];
300  int* ds = corenrn.get_memb_func(type).dparam_semantics;
301  int idep = 0;
302  if (ds)
303  for (int i = 0; i < dpsize; ++i) {
304  if (nrn_semantics_is_ion(ds[i])) {
305  int deptype = nrn_semantics_ion_type(ds[i]);
306  int idepnew = depend_append(idep, dependencies, deptype, type);
307  if ((idepnew > idep) && !corenrn.get_ion_write_dependency().empty() &&
308  !corenrn.get_ion_write_dependency()[deptype].empty()) {
309  auto& iwd = corenrn.get_ion_write_dependency()[deptype];
310  int size = iwd[0];
311  for (int j = 1; j < size; ++j) {
312  idepnew = depend_append(idepnew, dependencies, iwd[j], type);
313  }
314  }
315  idep = idepnew;
316  }
317  }
318  return idep;
319 }
320 
322  corenrn.get_memb_funcs().back().constructor = c;
323 }
324 
326  corenrn.get_memb_funcs().back().destructor = d;
327 }
328 
329 int point_reg_helper(const Symbol* s2) {
330  static int next_pointtype = 1; /* starts at 1 since 0 means not point in pnt_map */
331  int type = nrn_get_mechtype(s2);
332 
333  // No mechanism in the .dat files
334  if (type == -1)
335  return type;
336 
337  corenrn.get_pnt_map()[type] = next_pointtype++;
338  corenrn.get_memb_func(type).is_point = 1;
339 
340  return corenrn.get_pnt_map()[type];
341 }
342 
343 int point_register_mech(const char** m,
344  mod_alloc_t alloc,
345  mod_f_t cur,
346  mod_f_t jacob,
347  mod_f_t stat,
348  mod_f_t initialize,
349  mod_f_t private_constructor,
350  mod_f_t private_destructor,
351  int nrnpointerindex,
354  int vectorized) {
355  const Symbol* s = m[1];
356  register_mech(m,
357  alloc,
358  cur,
359  jacob,
360  stat,
361  initialize,
362  private_constructor,
363  private_destructor,
364  nrnpointerindex,
365  vectorized);
368  return point_reg_helper(s);
369 }
370 
371 void _modl_cleanup() {}
372 
375 void state_discontinuity(int /* i */, double* pd, double d) {
377  *pd = d;
378  /*printf("state_discontinuity t=%g pd=%lx d=%g\n", t, (long)pd, d);*/
379  }
380 }
381 
382 void hoc_reg_ba(int mt, mod_f_t f, int type) {
383  if (type == -1)
384  return;
385 
386  switch (type) { /* see bablk in src/nmodl/nocpout.c */
387  case 11:
389  break;
390  case 22:
391  type = AFTER_SOLVE;
392  break;
393  case 13:
395  break;
396  case 23:
398  break;
399  case 14:
400  type = BEFORE_STEP;
401  break;
402  default:
403  printf("before-after processing type %d for %s not implemented\n",
404  type,
405  corenrn.get_memb_func(mt).sym);
406  nrn_exit(1);
407  }
408  auto bam = (BAMech*) emalloc(sizeof(BAMech));
409  bam->f = f;
410  bam->type = mt;
411  bam->next = nullptr;
412  // keep in call order
413  if (!corenrn.get_bamech()[type]) {
414  corenrn.get_bamech()[type] = bam;
415  } else {
416  BAMech* last;
417  for (last = corenrn.get_bamech()[type]; last->next; last = last->next) {
418  }
419  last->next = bam;
420  }
421 }
422 
423 void _nrn_thread_reg0(int i, void (*f)(ThreadDatum*)) {
424  if (i == -1)
425  return;
426 
427  corenrn.get_memb_func(i).thread_cleanup_ = f;
428 }
429 
430 void _nrn_thread_reg1(int i, void (*f)(ThreadDatum*)) {
431  if (i == -1)
432  return;
433 
434  corenrn.get_memb_func(i).thread_mem_init_ = f;
435 }
436 
438  if (i == -1)
439  return;
440 
441  corenrn.get_memb_func(i).thread_table_check_ = f;
442 }
443 
444 void _nrn_setdata_reg(int i, void (*call)(double*, Datum*)) {
445  if (i == -1)
446  return;
447 
448  corenrn.get_memb_func(i).setdata_ = call;
449 }
450 
452  if (sym != nullptr) {
453  free(sym);
454  }
455  if (dparam_semantics != nullptr) {
456  free(dparam_semantics);
457  }
458 }
459 
460 } // namespace coreneuron
ReceiveFunc * pnt_receive
Definition: init.cpp:155
auto & get_memb_func(size_t idx)
Definition: coreneuron.hpp:135
auto & get_net_buf_send_type()
Definition: coreneuron.hpp:155
auto & get_ion_write_dependency()
Definition: coreneuron.hpp:147
auto & get_different_mechanism_type()
Definition: coreneuron.hpp:139
#define i
Definition: md1redef.h:19
static int indx
Definition: deriv.cpp:289
static int c
Definition: hoc.cpp:169
#define assert(ex)
Definition: hocassrt.h:24
static void call(Symbol *s, Node *nd, Prop *p)
Definition: hocmech.cpp:170
bool nrn_semantics_is_ion(int i)
Definition: ion_semantics.h:6
int nrn_semantics_from_ion(int type, int i)
Definition: ion_semantics.h:3
int nrn_semantics_ion_type(int i)
Definition: ion_semantics.h:12
#define AFTER_SOLVE
Definition: membfunc.hpp:70
#define BEFORE_INITIAL
Definition: membfunc.hpp:67
#define BEFORE_STEP
Definition: membfunc.hpp:71
#define AFTER_INITIAL
Definition: membfunc.hpp:68
#define EXTRACELL
Definition: membfunc.hpp:61
#define BEFORE_BREAKPOINT
Definition: membfunc.hpp:69
#define DEF_rev_dt
#define DEF_dt
#define DEF_secondorder
#define DEF_celsius
printf
Definition: extdef.h:5
const char * name
Definition: init.cpp:16
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
void nrn_exit(int err)
Definition: nrnoc_aux.cpp:30
void(*)(NrnThread *, Memb_list *, int) mod_f_t
Definition: membfunc.hpp:24
void hoc_reg_bbcore_read(int type, bbcore_read_t f)
void _nrn_layout_reg(int, int)
static void ion_write_depend(int type, int etype)
void _modl_cleanup()
int point_reg_helper(const Symbol *s2)
void _nrn_thread_reg0(int i, void(*f)(ThreadDatum *))
void hoc_reg_ba(int, mod_f_t, int)
void nrn_writes_conc(int, int)
int * nrn_fornetcon_type_
int state_discon_flag_
void set_pnt_receive(int type, pnt_receive_t pnt_receive, pnt_receive_t pnt_receive_init, short size)
void add_nrn_fornetcons(int, int)
void(*)(int, int, double *, Datum *, ThreadDatum *, NrnThread *, Memb_list *, int) thread_table_check_t
Definition: membfunc.hpp:27
void _nrn_thread_table_reg(int i, thread_table_check_t f)
int state_discon_allowed_
void _nrn_setdata_reg(int i, void(*call)(double *, Datum *))
void register_destructor(mod_f_t d)
int Datum
Definition: nrnconf.h:23
void hoc_register_net_receive_buffering(NetBufReceive_t, int)
int * nrn_fornetcon_index_
void(*)(double *, int *, int *, int *, int, int, double *, Datum *, ThreadDatum *, NrnThread *, Memb_list *, double) bbcore_read_t
Definition: membfunc.hpp:205
void hoc_reg_bbcore_write(int type, bbcore_write_t f)
int nrn_fornetcon_cnt_
void register_constructor(mod_f_t constructor)
void(*)(NrnThread *, Memb_list *) nrn_watch_check_t
Definition: membfunc.hpp:119
void add_nrn_artcell(int type, int qi)
void(*)(Point_process *, int, double) pnt_receive_t
Definition: membfunc.hpp:25
int nrn_mech_depend(int type, int *dependencies)
void state_discontinuity(int, double *pd, double d)
double celsius
void _nrn_thread_reg1(int i, void(*f)(ThreadDatum *))
void hoc_register_dparam_semantics(int type, int, const char *name)
void * erealloc(void *ptr, size_t size)
Definition: nrnoc_aux.cpp:94
CoreNeuron corenrn
Definition: multicore.cpp:53
void * ecalloc(size_t n, size_t size)
Definition: nrnoc_aux.cpp:85
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(*)(double *, Datum *, int) mod_alloc_t
Definition: membfunc.hpp:23
static int depend_append(int idep, int *dependencies, int deptype, int type)
void alloc_mech(int memb_func_size_)
int point_register_mech(const char **, 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, mod_f_t constructor, mod_f_t destructor, int vectorized)
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(*)(NrnThread *) NetBufReceive_t
Definition: membfunc.hpp:114
void(*)(double *, int *, int *, int *, int, int, double *, Datum *, ThreadDatum *, NrnThread *, Memb_list *, double) bbcore_write_t
Definition: membfunc.hpp:218
int nrn_is_ion(int)
void hoc_register_net_send_buffering(int)
void hoc_register_watch_check(nrn_watch_check_t, int)
void register_all_variables_offsets(int mech_id, SerializedNames variable_names)
void add_nrn_has_net_event(int)
void(*)() Pfrv
size_t j
s
Definition: multisend.cpp:521
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
pnt_receive_init_t * pnt_receive_init
Definition: init.cpp:156
static int memb_func_size_
Definition: init.cpp:144
static void * constructor(Object *ho)
Definition: seclist.cpp:52
static void destructor(void *v)
Definition: seclist.cpp:61
Definition: model.h:47
struct BAMech * next
Definition: membfunc.hpp:76