NEURON
nrncore_callbacks.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <unordered_map>
3 #include "nrncore_callbacks.h"
4 #include "nrnconf.h"
5 #include "nrnmpi.h"
6 #include "section.h"
7 #include "netcon.h"
8 #include "nrncvode.h"
9 #include "nrniv_mf.h"
10 #include "hocdec.h"
14 #include "parse.hpp"
15 #include "nrnran123.h" // globalindex written to globals.
16 #include "netcvode.h" // for nrnbbcore_vecplay_write and PreSyn.flag_
18 #include "vrecitem.h" // for nrnbbcore_vecplay_write
19 
20 #ifdef MINGW
21 #define RTLD_NOW 0
22 #define RTLD_GLOBAL 0
23 #define RTLD_NOLOAD 0
24 extern "C" {
25 extern void* dlopen_noerr(const char* name, int mode);
26 #define dlopen dlopen_noerr
27 extern void* dlsym(void* handle, const char* name);
28 extern int dlclose(void* handle);
29 extern char* dlerror();
30 }
31 #else
32 #if defined(HAVE_DLFCN_H)
33 #include <dlfcn.h>
34 #endif
35 #endif
36 
39 extern short* nrn_is_artificial_;
40 extern bool corenrn_direct;
41 extern int* bbcore_dparam_size;
42 extern double nrn_ion_charge(Symbol*);
43 extern CellGroup* cellgroups_;
45 extern char* pnt_map;
46 extern void* nrn_interthread_enqueue(NrnThread*);
47 
48 /** Populate function pointers by mapping function pointers for callback */
49 void map_coreneuron_callbacks(void* handle) {
50  for (int i=0; cnbs[i].name; ++i) {
51  void* sym = NULL;
52 #if defined(HAVE_DLFCN_H)
53  sym = dlsym(handle, cnbs[i].name);
54 #endif
55  if (!sym) {
56  fprintf(stderr, "Could not get symbol %s from CoreNEURON\n", cnbs[i].name);
57  hoc_execerror("dlsym returned NULL", NULL);
58  }
59  void** c = (void**)sym;
60  *c = (void*)(cnbs[i].f);
61  }
62 }
63 
64 void write_memb_mech_types_direct(std::ostream& s) {
65  // list of Memb_func names, types, point type info, is_ion
66  // and data, pdata instance sizes. If the mechanism is an eion type,
67  // the following line is the charge.
68  // Not all Memb_func are necessarily used in the model.
69  s << bbcore_write_version << std::endl;
70  s << n_memb_func << std::endl;
71  for (int type=2; type < n_memb_func; ++type) {
72  const char* w = " ";
73  Memb_func& mf = memb_func[type];
74  s << mf.sym->name << w << type << w
75  << int(pnt_map[type]) << w // the pointtype, 0 means not a POINT_PROCESS
76  << nrn_is_artificial_[type] << w
77  << nrn_is_ion(type) << w
78  << nrn_prop_param_size_[type] << w << bbcore_dparam_size[type] << std::endl;
79 
80  if (nrn_is_ion(type)) {
81  s << nrn_ion_charge(mf.sym) << std::endl;
82  }
83  }
84 }
85 
86 
87 
88 
89 // just for secondorder and Random123_globalindex and legacy units flag
90 int get_global_int_item(const char* name) {
91  if (strcmp(name, "secondorder") == 0) {
92  return secondorder;
93  }else if(strcmp(name, "Random123_global_index") == 0) {
95  }else if (strcmp(name, "_nrnunit_use_legacy_") == 0) {
96  return _nrnunit_use_legacy_;
97  }
98  return 0;
99 }
100 
101 // successively return global double info. Begin with p==NULL.
102 // Done when return NULL.
103 void* get_global_dbl_item(void* p, const char* & name, int& size, double*& val) {
104  Symbol* sp = (Symbol*)p;
105  if (sp == NULL) {
107  }
108  for (; sp; sp = sp->next) {
109  if (sp->type == VAR && sp->subtype == USERDOUBLE) {
110  name = sp->name;
111  if (ISARRAY(sp)) {
112  Arrayinfo* a = sp->arayinfo;
113  if (a->nsub == 1) {
114  size = a->sub[0];
115  val = new double[size];
116  for (int i=0; i < a->sub[0]; ++i) {
117  char n[256];
118  sprintf(n, "%s[%d]", sp->name, i);
119  val[i] = *hoc_val_pointer(n);
120  }
121  }
122  }else{
123  size = 0;
124  val = new double[1];
125  val[0] = *sp->u.pval;
126  }
127  return sp->next;
128  }
129  }
130  return NULL;
131 }
132 
133 
134 
135 /**
136  Copy weights from all coreneuron::NrnThread to NetCon instances.
137  This depends on the CoreNEURON weight order for each thread to be
138  the same as was originally sent from NEURON. See how that order
139  was constructed in CellGroup::mk_cgs_netcon_info.
140 **/
141 
142 void nrnthreads_all_weights_return(std::vector<double*>& weights) {
143  std::vector<int> iw(nrn_nthread); // index for each thread
144  Symbol* ncsym = hoc_lookup("NetCon");
145  hoc_List* ncl = ncsym->u.ctemplate->olist;
146  hoc_Item* q;
147  ITERATE(q, ncl) {
148  Object* ho = (Object*)VOIDITM(q);
149  NetCon* nc = (NetCon*)ho->u.this_pointer;
150  std::size_t ith = 0; // if no _vnt, put in thread 0
151  if (nc->target_ && nc->target_->_vnt) {
152  ith = std::size_t(((NrnThread*)(nc->target_->_vnt))->id);
153  }
154  for (int i = 0; i < nc->cnt_; ++i) {
155  nc->weight_[i] = weights[ith][iw[ith]++];
156  }
157  }
158 }
159 
160 /** @brief Return location for CoreNEURON to copy data into.
161  * The type is mechanism type or special negative type for voltage,
162  * i_membrane_, or time. See coreneuron/io/nrn_setup.cpp:stdindex2ptr.
163  * We allow coreneuron to copy to NEURON's AoS data as CoreNEURON knows
164  * how its data is arranged (SoA and possibly permuted).
165  * This function figures out the size (just for sanity check)
166  * and data pointer to be returned based on type and thread id.
167  * The ARTIFICIAL_CELL type case is special as there is no thread specific
168  * Memb_list for those.
169  */
170 size_t nrnthreads_type_return(int type, int tid, double*& data, double**& mdata) {
171  size_t n = 0;
172  data = NULL;
173  mdata = NULL;
174  if (tid >= nrn_nthread) {
175  return n;
176  }
177  NrnThread& nt = nrn_threads[tid];
178  if (type == voltage) {
179  data = nt._actual_v;
180  n = size_t(nt.end);
181  } else if (type == i_membrane_) { // i_membrane_
182  data = nt._nrn_fast_imem->_nrn_sav_rhs;
183  n = size_t(nt.end);
184  } else if (type == 0) { // time
185  data = &nt._t;
186  n = 1;
187  } else if (type > 0 && type < n_memb_func) {
188  Memb_list* ml = nt._ml_list[type];
189  if (ml) {
190  mdata = ml->data;
191  n = ml->nodecount;
192  }else{
193  // The single thread case is easy
194  if (nrn_nthread == 1) {
195  ml = memb_list + type;
196  mdata = ml->data;
197  n = ml->nodecount;
198  }else{
199  // mk_tml_with_art() created a cgs[id].mlwithart which appended
200  // artificial cells to the end. Turns out that
201  // cellgroups_[tid].type2ml[type]
202  // is the Memb_list we need. Sadly, by the time we get here, cellgroups_
203  // has already been deleted. So we defer deletion of the necessary
204  // cellgroups_ portion (deleting it on return from nrncore_run).
205  auto& ml = CellGroup::deferred_type2artml_[tid][type];
206  n = size_t(ml->nodecount);
207  mdata = ml->data;
208  }
209  }
210  }
211  return n;
212 }
213 
214 
215 void nrnthread_group_ids(int* grp) {
216  for (int i = 0; i < nrn_nthread; ++i) {
217  grp[i] = cellgroups_[i].group_id;
218  }
219 }
220 
221 
222 
223 int nrnthread_dat1(int tid, int& n_presyn, int& n_netcon,
224  int*& output_gid, int*& netcon_srcgid,
225  std::vector<int>& netcon_negsrcgid_tid) {
226 
227  if (tid >= nrn_nthread) { return 0; }
228  CellGroup& cg = cellgroups_[tid];
229  n_presyn = cg.n_presyn;
230  n_netcon = cg.n_netcon;
231  output_gid = cg.output_gid; cg.output_gid = NULL;
232  netcon_srcgid = cg.netcon_srcgid; cg.netcon_srcgid = NULL;
233  netcon_negsrcgid_tid = cg.netcon_negsrcgid_tid;
234  return 1;
235 }
236 
237 // sizes and total data count
238 int nrnthread_dat2_1(int tid, int& ngid, int& n_real_gid, int& nnode, int& ndiam,
239  int& nmech, int*& tml_index, int*& ml_nodecount, int& nidata, int& nvdata, int& nweight) {
240 
241  if (tid >= nrn_nthread) { return 0; }
242  CellGroup& cg = cellgroups_[tid];
243  NrnThread& nt = nrn_threads[tid];
244 
245  ngid = cg.n_output;
246  n_real_gid = cg.n_real_output;
247  nnode = nt.end;
248  ndiam = cg.ndiam;
249  nmech = cg.n_mech;
250 
251  cg.ml_vdata_offset = new int[nmech];
252  int vdata_offset = 0;
253  tml_index = new int[nmech];
254  ml_nodecount = new int[nmech];
255  MlWithArt& mla = cg.mlwithart;
256  for (size_t j = 0; j < mla.size(); ++j) {
257  int type = mla[j].first;
258  Memb_list* ml = mla[j].second;
259  tml_index[j] = type;
260  ml_nodecount[j] = ml->nodecount;
261  cg.ml_vdata_offset[j] = vdata_offset;
262  int* ds = memb_func[type].dparam_semantics;
263  for (int psz=0; psz < bbcore_dparam_size[type]; ++psz) {
264  if (ds[psz] == -4 || ds[psz] == -6 || ds[psz] == -7 || ds[psz] == 0) {
265  //printf("%s ds[%d]=%d vdata_offset=%d\n", memb_func[type].sym->name, psz, ds[psz], vdata_offset);
266  vdata_offset += ml->nodecount;
267  }
268  }
269  }
270  nvdata = vdata_offset;
271  nidata = 0;
272  // printf("nidata=%d nvdata=%d nnetcon=%d\n", nidata, nvdata, cg.n_netcon);
273  nweight = 0;
274  for (int i=0; i < cg.n_netcon; ++i) {
275  nweight += cg.netcons[i]->cnt_;
276  }
277 
278  return 1;
279 }
280 
281 int nrnthread_dat2_2(int tid, int*& v_parent_index, double*& a, double*& b,
282  double*& area, double*& v, double*& diamvec) {
283 
284  if (tid >= nrn_nthread) { return 0; }
285  CellGroup& cg = cellgroups_[tid];
286  NrnThread& nt = nrn_threads[tid];
287 
288  assert(cg.n_real_output == nt.ncell);
289 
290  // If direct transfer, copy, because target space already allocated
291  bool copy = corenrn_direct;
292  if (copy) {
293  for (int i=0; i < nt.end; ++i) {
294  v_parent_index[i] = nt._v_parent_index[i];
295  a[i] = nt._actual_a[i];
296  b[i] = nt._actual_b[i];
297  area[i] = nt._actual_area[i];
298  v[i] = nt._actual_v[i];
299  }
300  }else{
301  v_parent_index = nt._v_parent_index;
302  a = nt._actual_a;
303  b = nt._actual_b;
304  area = nt._actual_area;
305  v = nt._actual_v;
306  }
307  if (cg.ndiam) {
308  if (!copy) {
309  diamvec = new double[nt.end];
310  }
311  for (int i=0; i < nt.end; ++i) {
312  Node* nd = nt._v_node[i];
313  double diam = 0.0;
314  for (Prop* p = nd->prop; p; p = p->next) {
315  if (p->type == MORPHOLOGY) {
316  diam = p->param[0];
317  break;
318  }
319  }
320  diamvec[i] = diam;
321  }
322  }
323  return 1;
324 }
325 
326 int nrnthread_dat2_mech(int tid, size_t i, int dsz_inst, int*& nodeindices,
327  double*& data, int*& pdata, std::vector<int>& pointer2type) {
328 
329  if (tid >= nrn_nthread) { return 0; }
330  CellGroup& cg = cellgroups_[tid];
331  NrnThread& nt = nrn_threads[tid];
332  MlWithArtItem& mlai = cg.mlwithart[i];
333  int type = mlai.first;
334  Memb_list* ml = mlai.second;
335  // for direct transfer, data=NULL means copy into passed space for nodeindices, data, and pdata
336  bool copy = data ? true : false;
337 
338  int vdata_offset = cg.ml_vdata_offset[i];
339  int isart = nrn_is_artificial_[type];
340  int n = ml->nodecount;
341  int sz = nrn_prop_param_size_[type];
342  double* data1;
343  if (isart) { // data may not be contiguous
344  data1 = contiguous_art_data(ml->data, n, sz); // delete after use
345  nodeindices = NULL;
346  }else{
347  nodeindices = ml->nodeindices; // allocated below if copy
348  data1 = ml->data[0]; // do not delete after use
349  }
350  if (copy) {
351  if (!isart) {
352  nodeindices = (int*)emalloc(n*sizeof(int));
353  for (int i=0; i < n; ++i) {
354  nodeindices[i] = ml->nodeindices[i];
355  }
356  }
357  int nn = n*sz;
358  for (int i = 0; i < nn; ++i) {
359  data[i] = data1[i];
360  }
361  if (isart) {
362  delete [] data1;
363  }
364  }else{
365  data = data1;
366  }
367 
368  sz = bbcore_dparam_size[type]; // nrn_prop_dparam_size off by 1 if cvode_ieq.
369  if (sz) {
370  int* pdata1;
371  pdata1 = datum2int(type, ml, nt, cg, cg.datumindices[dsz_inst], vdata_offset, pointer2type);
372  if (copy) {
373  int nn = n*sz;
374  for (int i=0; i < nn; ++i) {
375  pdata[i] = pdata1[i];
376  }
377  delete [] pdata1;
378  }else{
379  pdata = pdata1;
380  }
381  }else{
382  pdata = NULL;
383  }
384 
385  return 1;
386 }
387 
388 int nrnthread_dat2_3(int tid, int nweight, int*& output_vindex, double*& output_threshold,
389  int*& netcon_pnttype, int*& netcon_pntindex, double*& weights, double*& delays) {
390 
391  if (tid >= nrn_nthread) { return 0; }
392  CellGroup& cg = cellgroups_[tid];
393 
394  output_vindex = new int[cg.n_presyn];
395  output_threshold = new double[cg.n_real_output];
396  for (int i=0; i < cg.n_presyn; ++i) {
397  output_vindex[i] = cg.output_vindex[i];
398  }
399  for (int i=0; i < cg.n_real_output; ++i) {
400  output_threshold[i] = cg.output_ps[i] ? cg.output_ps[i]->threshold_ : 0.0;
401  }
402 
403  // connections
404  int n = cg.n_netcon;
405  //printf("n_netcon=%d nweight=%d\n", n, nweight);
406  netcon_pnttype = cg.netcon_pnttype; cg.netcon_pnttype = NULL;
407  netcon_pntindex = cg.netcon_pntindex; cg.netcon_pntindex = NULL;
408  // alloc a weight array and write netcon weights
409  weights = new double[nweight];
410  int iw = 0;
411  for (int i=0; i < n; ++ i) {
412  NetCon* nc = cg.netcons[i];
413  for (int j=0; j < nc->cnt_; ++j) {
414  weights[iw++] = nc->weight_[j];
415  }
416  }
417  // alloc a delay array and write netcon delays
418  delays = new double[n];
419  for (int i=0; i < n; ++ i) {
420  NetCon* nc = cg.netcons[i];
421  delays[i] = nc->delay_;
422  }
423 
424  return 1;
425 }
426 
427 int nrnthread_dat2_corepointer(int tid, int& n) {
428 
429  if (tid >= nrn_nthread) { return 0; }
430 
431  n = 0;
432  MlWithArt& mla = cellgroups_[tid].mlwithart;
433  for (size_t i = 0; i < mla.size(); ++i) {
434  if (nrn_bbcore_write_[mla[i].first]) {
435  ++n;
436  }
437  }
438 
439  return 1;
440 }
441 
443  int& icnt, int& dcnt, int*& iArray, double*& dArray) {
444 
445  if (tid >= nrn_nthread) { return 0; }
446  NrnThread& nt = nrn_threads[tid];
447  CellGroup& cg = cellgroups_[tid];
448  Memb_list* ml = cg.type2ml[type];
449 
450  dcnt = 0;
451  icnt = 0;
452  // data size and allocate
453  for (int i = 0; i < ml->nodecount; ++i) {
454  (*nrn_bbcore_write_[type])(NULL, NULL, &dcnt, &icnt, ml->data[i], ml->pdata[i], ml->_thread, &nt);
455  }
456  dArray = NULL;
457  iArray = NULL;
458  if (icnt)
459  {
460  iArray = new int[icnt];
461  }
462  if (dcnt)
463  {
464  dArray = new double[dcnt];
465  }
466  icnt = dcnt = 0;
467  // data values
468  for (int i = 0; i < ml->nodecount; ++i) {
469  (*nrn_bbcore_write_[type])(dArray, iArray, &dcnt, &icnt, ml->data[i], ml->pdata[i], ml->_thread, &nt);
470  }
471 
472  return 1;
473 }
474 
475 
476 // primarily to return nrnran123 sequence info when psolve on the coreneuron
477 // side is finished so can either do another coreneuron psolve or
478 // continue on neuron side.
480  int icnt, int dcnt, int* iArray, double* dArray) {
481 
482  if (tid >= nrn_nthread) { return 0; }
483  NrnThread& nt = nrn_threads[tid];
484  Memb_list* ml = nt._ml_list[type];
485  // ARTIFICIAL_CELL are not in nt.
486  if (!ml) {
488  assert(ml);
489  }
490 
491  int ik = 0;
492  int dk = 0;
493  // data values
494  for (int i = 0; i < ml->nodecount; ++i) {
495  (*nrn_bbcore_read_[type])(dArray, iArray, &dk, &ik, ml->data[i], ml->pdata[i], ml->_thread, &nt);
496  }
497  assert(dk == dcnt);
498  assert(ik == icnt);
499  return 1;
500 }
501 
502 int* datum2int(int type, Memb_list* ml, NrnThread& nt, CellGroup& cg, DatumIndices& di, int ml_vdata_offset, std::vector<int>& pointer2type) {
503  int isart = nrn_is_artificial_[di.type];
504  int sz = bbcore_dparam_size[type];
505  int* pdata = new int[ml->nodecount * sz];
506  int* semantics = memb_func[type].dparam_semantics;
507  for (int i=0; i < ml->nodecount; ++i) {
508  int ioff = i*sz;
509  for (int j = 0; j < sz; ++j) {
510  int jj = ioff + j;
511  int etype = di.ion_type[jj];
512  int eindex = di.ion_index[jj];
513  const int seman = semantics[j];
514  // Would probably be more clear if use seman for as many as
515  // possible of the cases
516  // below and within each case deal with etype appropriately.
517  // ion_type and ion_index have become misnomers as they no longer
518  // refer to ions specificially but the mechanism type where the
519  // range variable lives (and otherwise is generally the same as
520  // seman). And ion_index refers to the index of the range variable
521  // within the mechanism (or voltage, area, etc.)
522  if (seman == -5) { // POINTER to range variable (e.g. voltage)
523  pdata[jj] = eindex;
524  pointer2type.push_back(etype);
525  }else if (etype == -1) {
526  if (isart) {
527  pdata[jj] = -1; // maybe save this space eventually. but not many of these in bb models
528  }else{
529  pdata[jj] = eindex;
530  }
531  }else if (etype == -9) {
532  pdata[jj] = eindex;
533  }else if (etype > 0 && etype < 1000){//ion pointer
534  pdata[jj] = eindex;
535  }else if (etype > 1000 && etype < 2000) { //ionstyle can be explicit instead of pointer to int*
536  pdata[jj] = eindex;
537  }else if (etype == -2) { // an ion and this is the iontype
538  pdata[jj] = eindex;
539  }else if (etype == -4) { // netsend (_tqitem)
540  pdata[jj] = ml_vdata_offset + eindex;
541  //printf("etype %d jj=%d eindex=%d pdata=%d\n", etype, jj, eindex, pdata[jj]);
542  }else if (etype == -6) { // pntproc
543  pdata[jj] = ml_vdata_offset + eindex;
544  //printf("etype %d jj=%d eindex=%d pdata=%d\n", etype, jj, eindex, pdata[jj]);
545  }else if (etype == -7) { // bbcorepointer
546  pdata[jj] = ml_vdata_offset + eindex;
547  //printf("etype %d jj=%d eindex=%d pdata=%d\n", etype, jj, eindex, pdata[jj]);
548  }else{ //uninterpreted
549  assert(eindex != -3); // avoided if last
550  pdata[jj] = 0;
551  }
552  }
553  }
554  return pdata;
555 }
556 
557 void part2_clean() {
559 
560  CellGroup::clean_art(cellgroups_);
561 
562  if (corenrn_direct) {
563  CellGroup::defer_clean_netcons(cellgroups_);
564  }
565 
566  delete [] cellgroups_;
567  cellgroups_ = NULL;
568 }
569 
570 std::vector<NetCon**> CellGroup::deferred_netcons;
571 
574  for (int tid = 0; tid < nrn_nthread; ++tid) {
575  CellGroup& cg = cgs[tid];
576  deferred_netcons.push_back(cg.netcons);
577  cg.netcons = nullptr;
578  }
579 }
580 
582  for (auto ncs: deferred_netcons) {
583  if (ncs) {
584  delete [] ncs;
585  }
586  }
587  deferred_netcons.clear();
588 }
589 
590 // Vector.play information.
591 // Must play into a data element in this thread
592 // File format is # of play instances in this thread (generally VecPlayContinuous)
593 // For each Play instance
594 // VecPlayContinuousType (4), pd (index), y.size, yvec, tvec
595 // Other VecPlay instance types are possible, such as VecPlayContinuous with
596 // a discon vector or VecPlayStep with a DT or tvec, but are not implemented
597 // at present. Assertion errors are generated if not type 0 of if we
598 // cannot determine the index into the NrnThread._data .
599 
600 int nrnthread_dat2_vecplay(int tid, std::vector<int>& indices) {
601  if (tid >= nrn_nthread) { return 0; }
602  NrnThread& nt = nrn_threads[tid];
603 
604  // add the index of each instance in fixed_play_ for thread tid.
605  // error if not a VecPlayContinuous with no discon vector
606  PlayRecList* fp = net_cvode_instance->fixed_play_;
607  for (int i=0; i < fp->count(); ++i){
608  if (fp->item(i)->type() == VecPlayContinuousType) {
609  VecPlayContinuous* vp = (VecPlayContinuous*)fp->item(i);
610  if (vp->discon_indices_ == NULL) {
611  if (vp->ith_ == nt.id) {
612  assert(vp->y_ && vp->t_);
613  indices.push_back(i);
614  }
615  }else{
616  assert(0);
617  }
618  }else{
619  assert(0);
620  }
621  }
622 
623  return 1;
624 }
625 
626 int nrnthread_dat2_vecplay_inst(int tid, int i, int& vptype, int& mtype,
627  int& ix, int& sz, double*& yvec, double*& tvec,
628  int& last_index, int& discon_index, int& ubound_index) {
629 
630  if (tid >= nrn_nthread) { return 0; }
631  NrnThread& nt = nrn_threads[tid];
632 
633  PlayRecList* fp = net_cvode_instance->fixed_play_;
634  if (fp->item(i)->type() == VecPlayContinuousType) {
635  VecPlayContinuous* vp = (VecPlayContinuous*)fp->item(i);
636  if (vp->discon_indices_ == NULL) {
637  if (vp->ith_ == nt.id) {
638  double* pd = vp->pd_;
639  int found = 0;
640  vptype = vp->type();
641  for (NrnThreadMembList* tml = nt.tml; tml; tml = tml->next) {
642  if (nrn_is_artificial_[tml->index]) { continue; }
643  Memb_list* ml = tml->ml;
644  int nn = nrn_prop_param_size_[tml->index] * ml->nodecount;
645  if (pd >= ml->data[0] && pd < (ml->data[0] + nn)) {
646  mtype = tml->index;
647  ix = (pd - ml->data[0]);
648  sz = vector_capacity(vp->y_);
649  yvec = vector_vec(vp->y_);
650  tvec = vector_vec(vp->t_);
651  found = 1;
652  break;
653  }
654  }
655  assert(found);
656  // following 3 used for direct-mode.
657  last_index = vp->last_index_;
658  discon_index = vp->discon_index_;
659  ubound_index = vp->ubound_index_;
660  return 1;
661  }
662  }
663  }
664 
665  return 0;
666 }
667 
668 /** getting one item at a time from CoreNEURON **/
669 void core2nrn_vecplay(int tid, int i, int last_index, int discon_index, int ubound_index) {
670  if (tid >= nrn_nthread) { return; }
671  PlayRecList* fp = net_cvode_instance->fixed_play_;
672  assert(fp->item(i)->type() == VecPlayContinuousType);
673  VecPlayContinuous* vp = (VecPlayContinuous*)fp->item(i);
674  vp->last_index_ = last_index;
675  vp->discon_index_ = discon_index;
676  vp->ubound_index_ = ubound_index;
677 }
678 
679 /** start the vecplay events **/
681  PlayRecList* fp = net_cvode_instance->fixed_play_;
682  for (int i=0; i < fp->count(); ++i){
683  if (fp->item(i)->type() == VecPlayContinuousType) {
684  VecPlayContinuous* vp = (VecPlayContinuous*)fp->item(i);
685  NrnThread* nt = nrn_threads + vp->ith_;
686  vp->e_->send(vp->t_->elem(vp->ubound_index_), net_cvode_instance, nt);
687  }
688  }
689 }
690 
691 /** getting one item at a time from nrn2core_transfer_WATCH **/
692 void nrn2core_transfer_WatchCondition(WatchCondition* wc, void(*cb)(int, int, int, int, int)) {
693  Point_process* pnt = wc->pnt_;
694  assert(pnt);
695  int tid = ((NrnThread*)(pnt->_vnt))->id;
696  int pnttype = pnt->prop->type;
697  int watch_index = wc->watch_index_;
698  int triggered = wc->flag_ ? 1 : 0;
699  int pntindex = CellGroup::nrncore_pntindex_for_queue(pnt->prop->param, tid, pnttype);
700  (*cb)(tid, pnttype, pntindex, watch_index, triggered);
701 
702  // This transfers CvodeThreadData activated WatchCondition
703  // information. All WatchCondition stuff is implemented in netcvode.cpp.
704  // cvodeobj.h: HTList* CvodeThreadData.watch_list_
705  // netcon.h: WatchCondition
706  // On the NEURON side, WatchCondition is activated within a
707  // NET_RECEIVE block with the NMODL WATCH statement translated into a
708  // call to _nrn_watch_activate implmented as a function in netcvode.cpp.
709  // Note that on the CoreNEURON side, all the WATCH functionality is
710  // implemented within the mod file translation, and the info from this side
711  // is used to assign a value in the location specified by the
712  // _watch_array(flag) macro.
713  // The return from psolve must transfer back the correct conditions
714  // so that NEURON can continue with a classical psolve, or, if CoreNEURON
715  // continues, receive the correct transfer of conditions back from NEURON
716  // again.
717  // Note: the reason CoreNEURON does not already have the correct watch
718  // condition from phase2 setup is because, on the NEURON side,
719  // _nrn_watch_activate fills in the _watch_array[0] with a pointer to
720  // WatchList and _watch_array[i] with a pointer to WatchCondition.
721  // Activation consists of removing all conditions from a HTList (HeadTailList)
722  // and _watch_array[0] (only on the first _nrn_watch_activate call from a
723  // NET_RECEIVE delivery event). And appending to _watch_array[0] and
724  // Append to the HTList which is the CvodeThreadData.watch_list_;
725  // But on the CoreNEURON side, _watch_array[0] is unused and _watch_array[i]
726  // is a two bit integer. Bit 2 on means the WATCH is activated Bit 1
727  // is used to determine the transition from false to true for doing a
728  // net_send (immediate deliver).
729 
730 }
731 
732 // for faster determination of the movable index given the type
733 static std::map<int, int> type2movable;
734 static void setup_type2semantics() {
735  if (type2movable.empty()) {
736  for (int type = 0; type < n_memb_func; ++type) {
737  int* ds = memb_func[type].dparam_semantics;
738  if (ds) {
739  for (int psz=0; psz < bbcore_dparam_size[type]; ++psz) {
740  if (ds[psz] == -4) { // netsend semantics
741  type2movable[type] = psz;
742  }
743  }
744  }
745  }
746  }
747 }
748 
749 // Copying TQItem information for transfer to CoreNEURON has been factored
750 // out of nrn2core_transfer_tqueue since, if BinQ is being used, it involves
751 // iterating over the BinQ as well as the normal TQueue.
752 static void set_info(TQItem* tqi, int tid, NrnCoreTransferEvents* core_te,
753  std::unordered_map<NetCon*, std::vector<size_t> >& netcon2intdata,
754  std::unordered_map<PreSyn*, std::vector<size_t> >& presyn2intdata,
755  std::unordered_map<double*, std::vector<size_t> >& weight2intdata) {
756 
757  DiscreteEvent* de = (DiscreteEvent*)(tqi->data_);
758  int type = de->type();
759  double tdeliver = tqi->t_;
760  core_te->type.push_back(type);
761  core_te->td.push_back(tdeliver);
762 
763  switch (type) {
764  case DiscreteEventType: { // 0
765  } break;
766  case TstopEventType: { // 1
767  } break;
768  case NetConType: { // 2
769  NetCon* nc = (NetCon*)de;
770  // To find the i for cg.netcons[i] == nc
771  // and since there are generally very many fewer nc on the queue
772  // than netcons. Begin a nc2i map that we can fill in for i
773  // later in one sweep through the cg.netcons.
774  // Here is where it goes.
775  size_t iloc = core_te->intdata.size();
776  core_te->intdata.push_back(-1);
777  // But must take into account the rare situation where the same
778  // NetCon is on the queue more than once. Hence the std::vector
779  netcon2intdata[nc].push_back(iloc);
780  } break;
781  case SelfEventType: { //3
782  SelfEvent* se = (SelfEvent*)de;
783  Point_process* pnt = se->target_;
784  int type = pnt->prop->type;
785  int movable_index = type2movable[type];
786  double* wt = se->weight_;
787 
788  core_te->intdata.push_back(type);
789  core_te->dbldata.push_back(se->flag_);
790 
791  // All SelfEvent have a target. A SelfEvent only has a weight if
792  // it was issued in response to a NetCon event to the target
793  // NET_RECEIVE block. Determination of Point_process* target_ on the
794  // CoreNEURON side uses mechanism type and instance index from here
795  // on the NEURON side. And the latter can be determined now from pnt.
796  // On the other hand, if there is a non-null weight pointer, its index
797  // can only be determined by sweeping over all NetCon.
798 
799  double* data = pnt->prop->param;
800  // Introduced the public static method below because ARTIFICIAL_CELL
801  // are not located in NrnThread and are not cache efficient.
802  int index = CellGroup::nrncore_pntindex_for_queue(data, tid, type);
803  core_te->intdata.push_back(index);
804 
805  size_t iloc_wt = core_te->intdata.size();
806  if (wt) { // don't bother with NULL weights
807  weight2intdata[wt].push_back(iloc_wt);
808  }
809  core_te->intdata.push_back(-1); // If NULL weight this is the indicator
810 
811  TQItem** movable = (TQItem**)se->movable_;
812  TQItem** pnt_movable = (TQItem**)(&pnt->prop->dparam[movable_index]);
813  // Only one SelfEvent on the queue for a given point process can be movable
814  core_te->intdata.push_back((movable && *movable == tqi) ? 1 : 0);
815  if (movable && *movable == tqi) {
816  assert(pnt_movable && *pnt_movable == tqi);
817  }
818 
819  } break;
820  case PreSynType: { // 4
821  PreSyn* ps = (PreSyn*)de;
822 
823  // NEURON puts PreSyn on every thread queue
824  // Skip if PreSyn not associated with this thread.
825  bool skip = (ps->nt_ && (ps->nt_->id != tid)) ? true : false;
826  // Skip if effectively an InputPresyn (ps->nt_ == NULL)
827  // and this is not thread 0.
828  skip = (!ps->nt_ && tid != 0) ? true : skip;
829  if (skip) {
830  // erase what was already added
831  core_te->type.pop_back();
832  core_te->td.pop_back();
833  break;
834  }
835  // Output PreSyn similar to NetCon but more data.
836  // Input PreSyn (ps->output_index = -1 and ps->gid >= 0)
837  // is distinquished from PreSyn (ps->output_index == ps->gid
838  // or both negative) by the first item of 0 or 1 respectively followed
839  // by gid or presyn index respectively.
840  // That is:
841  // Output PreSyn format is 0, presyn index
842  // initialized to -1 and figured out from presyn2intdata, and
843  // ps->delay_
844  // Input PreSyn format is 1, gid, and ps->delay_
845  if (ps->output_index_ < 0 && ps->gid_ >= 0) {
846  // InputPreSyn on the CoreNEURON side
847  core_te->intdata.push_back(1);
848  core_te->intdata.push_back(ps->gid_);
849  }else{
850  // PreSyn on the NEURON side
851  core_te->intdata.push_back(0);
852  size_t iloc = core_te->intdata.size();
853  core_te->intdata.push_back(-1);
854  presyn2intdata[ps].push_back(iloc);
855  }
856  // CoreNEURON PreSyn has no notion of use_min_delay_ so if that
857  // is in effect, then the send time is actually tt - nc->delay_
858  // (Note there is no core2nrn inverse as PreSyn does not appear on
859  // the CoreNEURON event queue).
860  if (ps->use_min_delay_) {
861  core_te->td.back() -= ps->delay_;
862  }
863  } break;
864  case HocEventType: { // 5
865  // Not supported in CoreNEURON, discard and print a warning.
866  core_te->td.pop_back();
867  core_te->type.pop_back();
868  // Delivery time was often reduced by a quarter step to avoid
869  // fixed step roundoff problems.
870  Fprintf(stderr, "WARNING: CVode.event(...) for delivery at time step nearest %g discarded. CoreNEURON cannot presently handle interpreter events (rank %d, thread %d).\n", nrnmpi_myid, tdeliver, nrnmpi_myid, tid);
871  } break;
872  case PlayRecordEventType: { // 6
873  } break;
874  case NetParEventType: { // 7
875  } break;
876  default: {
877  } break;
878  }
879 }
880 
882  if (tid >= nrn_nthread) { return NULL; }
883 
885 
887 
888  // see comments below about same object multiple times on queue
889  // and single sweep fill
890  std::unordered_map<NetCon*, std::vector<size_t> > netcon2intdata;
891  std::unordered_map<PreSyn*, std::vector<size_t> > presyn2intdata;
892  std::unordered_map<double*, std::vector<size_t> > weight2intdata;
893 
894  NrnThread& nt = nrn_threads[tid];
896  TQItem* tqi;
897  auto& cg = cellgroups_[tid];
898  // make sure all buffered interthread events are on the queue
900 
901  // Iterate over all tqueue items to record info needed for transfer to
902  // coreneuron. The atomic_dq removes items from the queue but misses
903  // BinQ items if present. So need separate iteration for that (hence the
904  // factoring out of the loop bodies into set_info.)
905  while ((tqi = tq->atomic_dq(1e15)) != NULL) {
906  set_info(tqi, tid, core_te, netcon2intdata, presyn2intdata, weight2intdata);
907  }
908  if (nrn_use_bin_queue_) {
909  // does not remove items but the entire queue will be cleared
910  // before using again.
911  for (tqi = tq->binq()->first(); tqi; tqi = tq->binq()->next(tqi)) {
912  set_info(tqi, tid, core_te, netcon2intdata, presyn2intdata, weight2intdata);
913  }
914  }
915 
916  // fill in the integers for the pointer translation
917 
918  // NEURON NetCon* to CoreNEURON index into nt.netcons
919  for (int i = 0; i < cg.n_netcon; ++i) {
920  NetCon* nc = cg.netcons[i];
921  auto iter = netcon2intdata.find(nc);
922  if (iter != netcon2intdata.end()) {
923  for (auto iloc: iter->second) {
924  core_te->intdata[iloc] = i;
925  }
926  }
927  }
928 
929  // NEURON PreSyn* to CoreNEURON index into nt.presyns
930 #define NRN_SENTINAL 100000000000
931  for (int i = 0; i < cg.n_presyn; ++i) {
932  PreSyn* ps = cg.output_ps[i];
933  auto iter = presyn2intdata.find(ps);
934  if (iter != presyn2intdata.end()) {
935  // not visited twice
936  assert(iter->second[0] < NRN_SENTINAL);
937  for (auto iloc: iter->second) {
938  core_te->intdata[iloc] = i;
939  }
940  presyn2intdata[ps][0] = i + NRN_SENTINAL;
941  }
942  }
943  // all presyn2intdata should have been visited so all
944  // presyn2intdata[ps][0] must be >= NRN_SENTINAL
945  for (auto& iter: presyn2intdata) {
946  assert(iter.second[0] >= NRN_SENTINAL);
947  }
948 
949  // NEURON SelfEvent weight* into CoreNEURON index into nt.netcons
950  // On the CoreNEURON side we find the NetCon and then the
951  // nc.u.weight_index_
952  for (int i = 0; i < cg.n_netcon; ++i) {
953  NetCon* nc = cg.netcons[i];
954  double* wt = nc->weight_;
955  auto iter = weight2intdata.find(wt);
956  if (iter != weight2intdata.end()) {
957  for (auto iloc: iter->second) {
958  core_te->intdata[iloc] = i;
959  }
960  }
961  }
962 
963  return core_te;
964 }
965 
966 /** @brief Initialize queues before transfer
967  Probably aleady clear, but if binq then must be initialized to time.
968  */
969 void core2nrn_clear_queues(double time) {
970  nrn_threads[0]._t = time; // used by clear_event_queue
972 }
973 
974 /** @brief Called from CoreNEURON core2nrn_tqueue_item.
975  */
976 void core2nrn_NetCon_event(int tid, double td, size_t nc_index) {
977  assert(tid < nrn_nthread);
978  NrnThread& nt = nrn_threads[tid];
979  // cellgroups_ has been deleted but deletion of cg.netcons was deferred
980  // (and will be deleted on return from nrncore_run).
981  // This is tragic for memory usage. There are more NetCon's than anything.
982  // Would be better to save the memory at a cost of single iteration over
983  // NetCon.
984  NetCon* nc = CellGroup::deferred_netcons[tid][nc_index];
985  nc->send(td, net_cvode_instance, &nt);
986 }
987 
988 static void core2nrn_SelfEvent_helper(int tid, double td,
989  int tar_type, int tar_index,
990  double flag, double* weight, int is_movable)
991 {
992  if (type2movable.empty()) {
994  }
995  Memb_list* ml = nrn_threads[tid]._ml_list[tar_type];
996  Point_process* pnt;
997  if (ml) {
998  pnt = (Point_process*)ml->pdata[tar_index][1]._pvoid;
999  } else {
1000  // In NEURON world, ARTIFICIAL_CELLs do not live in NrnThread.
1001  // And the old deferred_type2artdata_ only gave us data, not pdata.
1002  // So this is where I decided to replace the more
1003  // expensive deferred_type2artml_.
1004  ml = CellGroup::deferred_type2artml_[tid][tar_type];
1005  pnt = (Point_process*)ml->pdata[tar_index][1]._pvoid;
1006  }
1007 
1008  // Needs to be tested when permuted on CoreNEURON side.
1009  assert(tar_type == pnt->prop->type);
1010 // assert(tar_index == CellGroup::nrncore_pntindex_for_queue(pnt->prop->param, tid, tar_type));
1011 
1012  int movable_index = type2movable[tar_type];
1013  void** movable_arg = &(pnt->prop->dparam[movable_index]._pvoid);
1014  TQItem* old_movable_arg = (TQItem*)(*movable_arg);
1015 
1016  nrn_net_send(&(pnt->prop->dparam[movable_index]._pvoid), weight, pnt, td, flag);
1017  if (!is_movable) {
1018  *movable_arg = (void*)old_movable_arg;
1019  }
1020 }
1021 
1022 void core2nrn_SelfEvent_event(int tid, double td,
1023  int tar_type, int tar_index,
1024  double flag, size_t nc_index, int is_movable)
1025 {
1026  assert(tid < nrn_nthread);
1027  NetCon* nc = CellGroup::deferred_netcons[tid][nc_index];
1028 
1029 #if 1
1030  // verify nc->target_ consistent with tar_type, tar_index.
1031  Memb_list* ml = nrn_threads[tid]._ml_list[tar_type];
1032  Point_process* pnt = (Point_process*)ml->pdata[tar_index][1]._pvoid;
1033  assert(nc->target_ == pnt);
1034 #endif
1035 
1036  double* weight = nc->weight_;
1037  core2nrn_SelfEvent_helper(tid, td, tar_type, tar_index, flag, weight, is_movable);
1038 }
1039 
1040 void core2nrn_SelfEvent_event_noweight(int tid, double td,
1041  int tar_type, int tar_index,
1042  double flag, int is_movable)
1043 {
1044  assert(tid < nrn_nthread);
1045  double* weight = NULL;
1046  core2nrn_SelfEvent_helper(tid, td, tar_type, tar_index, flag, weight, is_movable);
1047 }
1048 
1049 //Set of the voltage indices in which PreSyn.flag_ == true
1050 void core2nrn_PreSyn_flag(int tid, std::set<int> presyns_flag_true) {
1051  if (tid >= nrn_nthread) {
1052  return;
1053  }
1054  NetCvodeThreadData& nctd = net_cvode_instance->p[tid];
1055  hoc_Item* pth = nctd.psl_thr_;
1056  if (pth) {
1057  hoc_Item* q;
1058  // turn off all the PreSyn.flag_ as they might have been turned off
1059  // during the psolve on the coreneuron side.
1060  ITERATE(q, pth) {
1061  PreSyn* ps = (PreSyn*)VOIDITM(q);
1062  ps->flag_ = false;
1063  }
1064  if (presyns_flag_true.empty()) {
1065  return;
1066  }
1067  ITERATE(q, pth) {
1068  PreSyn* ps = (PreSyn*)VOIDITM(q);
1069  assert(ps->nt_ == (nrn_threads + tid));
1070  if (ps->thvar_) {
1071  int type = 0;
1072  int index_v = -1;
1073  nrn_dblpntr2nrncore(ps->thvar_, *ps->nt_, type, index_v);
1074  assert(type == voltage);
1075  if(presyns_flag_true.erase(index_v)) {
1076  ps->flag_ = true;
1077  if (presyns_flag_true.empty()) {
1078  break;
1079  }
1080  }
1081  }
1082  }
1083  }
1084 }
1085 
1086 // Add the voltage indices in which PreSyn.flag_ == true to the set.
1087 void nrn2core_PreSyn_flag(int tid, std::set<int>& presyns_flag_true) {
1088  if (tid >= nrn_nthread) {
1089  return;
1090  }
1091  NetCvodeThreadData& nctd = net_cvode_instance->p[tid];
1092  hoc_Item* pth = nctd.psl_thr_;
1093  if (pth) {
1094  hoc_Item* q;
1095  ITERATE(q, pth) {
1096  PreSyn* ps = (PreSyn*)VOIDITM(q);
1097  assert(ps->nt_ == (nrn_threads + tid));
1098  if (ps->flag_ == true && ps->thvar_) {
1099  int type = 0;
1100  int index_v = -1;
1101  nrn_dblpntr2nrncore(ps->thvar_, *ps->nt_, type, index_v);
1102  assert(type == voltage);
1103  presyns_flag_true.insert(index_v);
1104  }
1105  }
1106  }
1107 }
1108 
1109 // For each watch index, activate the WatchCondition
1110 void core2nrn_watch_activate(int tid, int type, int watch_begin, Core2NrnWatchInfo& wi) {
1111  if (tid >= nrn_nthread) {
1112  return;
1113  }
1114  NrnThread& nt = nrn_threads[tid];
1115  Memb_list* ml = nt._ml_list[type];
1116  for (size_t i = 0; i < wi.size(); ++i) {
1117  Core2NrnWatchInfoItem& active_watch_items = wi[i];
1118  Datum* pd = ml->pdata[i];
1119  int r = 0; // first activate removes formerly active from pd.
1120  for (auto watch_item: active_watch_items){
1121  int watch_index = watch_item.first;
1122  bool above_thresh = watch_item.second;
1123  WatchCondition* wc = (WatchCondition*)pd[watch_index]._pvoid;
1124  if (!wc) { // if any do not exist in this instance, create them all
1125  // with proper callback and flag.
1126  (*(nrn_watch_allocate_[type]))(pd);
1127  wc = (WatchCondition*)pd[watch_index]._pvoid;
1128  }
1129  _nrn_watch_activate(pd + watch_begin, wc->c_, watch_index - watch_begin, wc->pnt_,
1130  r++, wc->nrflag_);
1131  wc->flag_ = above_thresh ? 1 : 0;
1132  // If flag_ is 1
1133  // there will not be a (immediate) transition event
1134  // til the value() becomes negative again and then goes positive.
1135  }
1136  }
1137 }
1138 
1139 // nrn<->corenrn PatternStim
1140 
1141 extern "C" { void* nrn_patternstim_info_ref(Datum*); }
1142 static int patternstim_type;
1143 
1144 // Info from NEURON PatternStim at beginning of psolve.
1146  if (!patternstim_type) {
1147  for (int i = 3; i < n_memb_func; ++i) {
1148  if (strcmp(memb_func[i].sym->name, "PatternStim") == 0) {
1149  patternstim_type = i;
1150  break;
1151  }
1152  }
1153  }
1154 
1156  assert(ml.nodecount == 1);
1157  *info = nrn_patternstim_info_ref(ml.pdata[0]);
1158 }
int nrnthread_dat2_3(int tid, int nweight, int *&output_vindex, double *&output_threshold, int *&netcon_pnttype, int *&netcon_pntindex, double *&weights, double *&delays)
static void setup_type2semantics()
static core2nrn_callback_t cnbs[]
#define data
Definition: rbtqueue.cpp:49
short * nrn_is_artificial_
Definition: init.cpp:231
Memb_list ** _ml_list
Definition: multicore.h:63
int cnt_
Definition: netcon.h:109
void clear_event_queue()
Definition: cvodestb.cpp:57
#define area
Definition: md1redef.h:5
std::vector< double > td
int n_output
Definition: cell_group.h:28
static Deferred_Type2ArtMl deferred_type2artml_
Definition: cell_group.h:76
double * param
Definition: section.h:218
int nrnthread_dat2_2(int tid, int *&v_parent_index, double *&a, double *&b, double *&area, double *&v, double *&diamvec)
#define assert(ex)
Definition: hocassrt.h:26
bool flag_
Definition: netcon.h:180
void core2nrn_NetCon_event(int tid, double td, size_t nc_index)
Called from CoreNEURON core2nrn_tqueue_item.
short type
Definition: cabvars.h:10
return true
Definition: savstate.cpp:357
int nrnthread_dat2_mech(int tid, size_t i, int dsz_inst, int *&nodeindices, double *&data, int *&pdata, std::vector< int > &pointer2type)
void * _vnt
Definition: section.h:269
static void clean_art(CellGroup *)
Definition: cell_group.cpp:587
char * pnt_map
Definition: init.cpp:166
void * _pvoid
Definition: hocdec.h:186
std::vector< std::pair< int, bool > > Core2NrnWatchInfoItem
double * contiguous_art_data(double **data, int nitem, int szitem)
Definition: nrncore_io.cpp:290
std::vector< MlWithArtItem > MlWithArt
Definition: cell_group.h:16
Definition: netcon.h:232
double(* c_)(Point_process *)
Definition: netcon.h:209
struct NrnThreadMembList * next
Definition: multicore.h:34
int group_id
Definition: cell_group.h:25
if(status)
short type
Definition: model.h:58
const char * dlerror(void)
Definition: osxdlfcn.cpp:174
int nsub
Definition: hocdec.h:70
NetCvode * net_cvode_instance
Definition: cvodestb.cpp:27
int * ml_vdata_offset
Definition: cell_group.h:32
int nrn_dblpntr2nrncore(double *pd, NrnThread &nt, int &type, int &index)
static int nrncore_pntindex_for_queue(double *d, int tid, int type)
Definition: cell_group.h:96
#define ITERATE(itm, lst)
Definition: model.h:25
NrnThread * nt_
Definition: netcon.h:270
Symbol * hoc_lookup(const char *)
int * _v_parent_index
Definition: multicore.h:76
void core2nrn_vecplay_events()
start the vecplay events
void * this_pointer
Definition: hocdec.h:231
size_t p
Represent main neuron object computed by single thread.
Definition: multicore.h:58
int * netcon_pnttype
Definition: cell_group.h:44
DatumIndices * datumindices
Definition: cell_group.h:48
static int first
Definition: fmenu.cpp:186
int output_index_
Definition: netcon.h:276
void * nrn_interthread_enqueue(NrnThread *)
Definition: netcvode.cpp:6730
void core2nrn_vecplay(int tid, int i, int last_index, int discon_index, int ubound_index)
getting one item at a time from CoreNEURON
PlayRecordEvent * e_
Definition: vrecitem.h:254
void core2nrn_PreSyn_flag(int tid, std::set< int > presyns_flag_true)
int _nrnunit_use_legacy_
Definition: hoc_init.cpp:273
PlayRecList * fixed_play_
Definition: netcvode.h:120
char * name
Definition: model.h:72
void core2nrn_SelfEvent_event_noweight(int tid, double td, int tar_type, int tar_index, double flag, int is_movable)
void nrn2core_PreSyn_flag(int tid, std::set< int > &presyns_flag_true)
Memb_func * memb_func
Definition: init.cpp:161
virtual void send(double sendtime, NetCvode *, NrnThread *)
Definition: netcvode.cpp:3088
nd
Definition: treeset.cpp:893
Point_process * target_
Definition: netcon.h:106
int nrnthread_dat2_vecplay(int tid, std::vector< int > &indices)
#define Fprintf
Definition: model.h:249
#define v
Definition: md1redef.h:4
double ** data
Definition: nrnoc_ml.h:14
#define NRN_SENTINAL
#define PreSynType
Definition: netcon.h:47
double t_
Definition: bbtqueue.h:18
#define nodeindices
Definition: md1redef.h:26
int nrnthread_dat2_1(int tid, int &ngid, int &n_real_gid, int &nnode, int &ndiam, int &nmech, int *&tml_index, int *&ml_nodecount, int &nidata, int &nvdata, int &nweight)
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
#define PlayRecordEventType
Definition: netcon.h:49
Definition: bbtqueue.h:6
double delay_
Definition: netcon.h:104
int dlclose(void *handle)
Definition: osxdlfcn.cpp:178
#define MORPHOLOGY
Definition: membfunc.h:63
int nrnthread_dat2_corepointer(int tid, int &n)
double * pd_
Definition: vrecitem.h:78
Point_process * pnt_
Definition: netcon.h:208
hoc_List * olist
Definition: hocdec.h:203
_nrn_Fast_Imem * _nrn_fast_imem
Definition: multicore.h:82
Datum * _thread
Definition: nrnoc_ml.h:17
static List * info
static std::vector< NetCon ** > deferred_netcons
Definition: cell_group.h:77
int watch_index_
Definition: netcon.h:214
j< sec-> nnode
Definition: treeset.cpp:905
MlWithArt mlwithart
Definition: cell_group.h:49
short type
Definition: section.h:215
int nrnthread_dat2_corepointer_mech(int tid, int type, int &icnt, int &dcnt, int *&iArray, double *&dArray)
TQItem * atomic_dq(double til)
Definition: sptbinq.cpp:251
void nrn2core_transfer_WatchCondition(WatchCondition *wc, void(*cb)(int, int, int, int, int))
getting one item at a time from nrn2core_transfer_WATCH
int get_global_int_item(const char *name)
int id
Definition: multicore.h:66
NrnCoreTransferEvents * nrn2core_transfer_tqueue(int tid)
static int pntindex
Definition: prcellstate.cpp:19
TQItem * first()
Iterate in ascending bin order starting at current bin.
Definition: sptbinq.cpp:355
int ncell
Definition: multicore.h:64
std::pair< int, Memb_list *> MlWithArtItem
Definition: cell_group.h:13
int * output_vindex
Definition: cell_group.h:36
int use_min_delay_
Definition: netcon.h:274
double nrn_ion_charge(Symbol *)
Definition: eion.cpp:55
Symbol * sym
Definition: membfunc.h:38
#define ncs
static Frame * fp
Definition: code.cpp:154
int nrn_nthread
Definition: multicore.cpp:44
Node ** _v_node
Definition: multicore.h:77
int sub[1]
Definition: hocdec.h:72
int const size_t const size_t n
Definition: nrngsl.h:12
IvocVect * t_
Definition: vrecitem.h:248
void(*)(double *, int *, int *, int *, double *, Datum *, Datum *, NrnThread *) bbcore_write_t
Definition: init.cpp:189
double threshold_
Definition: netcon.h:262
int nodecount
Definition: nrnoc_ml.h:18
_CONST char * s
Definition: system.cpp:74
NrnThread * nrn_threads
Definition: multicore.cpp:45
static int patternstim_type
double * _nrn_sav_rhs
Definition: multicore.h:46
Memb_list * memb_list
Definition: init.cpp:162
int val
Definition: dll.cpp:167
std::vector< int > intdata
Arrayinfo * arayinfo
Definition: hocdec.h:158
int * bbcore_dparam_size
Prop * prop
Definition: section.h:264
virtual int type()
Definition: vrecitem.h:244
bbcore_write_t * nrn_bbcore_write_
Definition: init.cpp:190
NetCon ** netcons
Definition: cell_group.h:38
double nrflag_
Definition: netcon.h:207
#define VOIDITM(q)
Definition: hoclist.h:68
int
Definition: nrnmusic.cpp:71
static void clean_deferred_netcons()
BinQ * binq()
Definition: sptbinq.h:97
size_t nrnthreads_type_return(int type, int tid, double *&data, double **&mdata)
Return location for CoreNEURON to copy data into.
#define ISARRAY(arg)
Definition: hocdec.h:163
virtual int type()
Definition: netcon.h:69
CellGroup * cellgroups_
void nrnthread_group_ids(int *grp)
int n_memb_func
Definition: init.cpp:471
#define DiscreteEventType
Definition: netcon.h:43
void * get_global_dbl_item(void *p, const char *&name, int &size, double *&val)
bbcore_write_t * nrn_bbcore_read_
Definition: init.cpp:191
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
void ** movable_
Definition: netcon.h:152
int core2nrn_corepointer_mech(int tid, int type, int icnt, int dcnt, int *iArray, double *dArray)
double * thvar_
Definition: netcon.h:264
#define NetConType
Definition: netcon.h:45
double * pval
Definition: hocdec.h:136
size_t j
Datum ** pdata
Definition: nrnoc_ml.h:15
#define USERDOUBLE
Definition: hocdec.h:93
static void defer_clean_netcons(CellGroup *)
fprintf(stderr, "Don't know the location of params at %p\, pp)
void cb(const char *s)
Definition: bbstest.cpp:5
Definition: model.h:57
int * output_gid
Definition: cell_group.h:35
virtual void send(double deliverytime, NetCvode *, NrnThread *)
Definition: netcvode.cpp:3069
Definition: section.h:213
void * nrn_patternstim_info_ref(Datum *)
char * name
Definition: init.cpp:16
int nrnthread_dat1(int tid, int &n_presyn, int &n_netcon, int *&output_gid, int *&netcon_srcgid, std::vector< int > &netcon_negsrcgid_tid)
double & elem(int n)
Definition: ivocvect.h:31
double * weight_
Definition: netcon.h:151
int n_mech
Definition: cell_group.h:31
PreSyn ** output_ps
Definition: cell_group.h:34
void _nrn_watch_activate(Datum *, double(*)(Point_process *), int, Point_process *, int, double)
Definition: netcvode.cpp:2431
Definition: netcon.h:82
char * emalloc(unsigned n)
Definition: list.cpp:189
int n_presyn
Definition: cell_group.h:27
int * nrn_prop_param_size_
Definition: init.cpp:178
double * weight_
Definition: netcon.h:107
int gid_
Definition: netcon.h:277
NetCvodeThreadData * p
Definition: netcvode.h:211
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:39
void nrn2core_patternstim(void **info)
double * _actual_a
Definition: multicore.h:72
double flag_
Definition: netcon.h:149
static std::map< int, int > type2movable
HocStruct Symbol * next
Definition: hocdec.h:161
int end
Definition: multicore.h:65
Datum * dparam
Definition: section.h:219
std::vector< Core2NrnWatchInfoItem > Core2NrnWatchInfo
int * netcon_srcgid
Definition: cell_group.h:39
long subtype
Definition: model.h:59
VEC * cgs(MTX_FN A, void *A_params, VEC *b, VEC *r0, double tol, VEC *x)
Definition: conjgrad.c:179
NrnWatchAllocateFunc_t * nrn_watch_allocate_
Definition: init.cpp:182
int vector_capacity(Vect *v)
Definition: ivocvect.cpp:268
double _t
Definition: multicore.h:59
const char * bbcore_write_version
Definition: nrncore_io.cpp:25
std::vector< int > netcon_negsrcgid_tid
Definition: cell_group.h:41
IvocVect * y_
Definition: vrecitem.h:247
int nrnthread_dat2_vecplay_inst(int tid, int i, int &vptype, int &mtype, int &ix, int &sz, double *&yvec, double *&tvec, int &last_index, int &discon_index, int &ubound_index)
int nrnmpi_myid
Definition: hocdec.h:226
HocStruct cTemplate * ctemplate
Definition: hocdec.h:151
void write_memb_mech_types_direct(std::ostream &s)
double * hoc_val_pointer(const char *s)
Definition: code2.cpp:699
void part2_clean()
static void core2nrn_SelfEvent_helper(int tid, double td, int tar_type, int tar_index, double flag, double *weight, int is_movable)
void core2nrn_watch_activate(int tid, int type, int watch_begin, Core2NrnWatchInfo &wi)
#define i
Definition: md1redef.h:12
#define VecPlayContinuousType
Definition: vrecitem.h:22
void nrn_net_send(void **, double *, Point_process *, double, double)
#define c
std::vector< double > dbldata
bool corenrn_direct
double * vector_vec(Vect *v)
Definition: ivocvect.cpp:271
void nrnthreads_all_weights_return(std::vector< double *> &weights)
Copy weights from all coreneuron::NrnThread to NetCon instances.
int * datum2int(int type, Memb_list *ml, NrnThread &nt, CellGroup &cg, DatumIndices &di, int ml_vdata_offset, std::vector< int > &pointer2type)
bool nrn_use_bin_queue_
Definition: netcvode.cpp:251
#define SelfEventType
Definition: netcon.h:46
hoc_Item * psl_thr_
Definition: netcvode.h:49
void core2nrn_clear_queues(double time)
Initialize queues before transfer Probably aleady clear, but if binq then must be initialized to time...
void map_coreneuron_callbacks(void *handle)
Populate function pointers by mapping function pointers for callback.
double * _actual_area
Definition: multicore.h:75
void core2nrn_SelfEvent_event(int tid, double td, int tar_type, int tar_index, double flag, size_t nc_index, int is_movable)
std::vector< int > type
int * dparam_semantics
Definition: membfunc.h:56
NrnThreadMembList * tml
Definition: multicore.h:62
void * dlsym(void *handle, const char *symbol)
Definition: osxdlfcn.cpp:193
static void clear_artdata2index()
Definition: cell_group.h:60
void * data_
Definition: bbtqueue.h:17
union Symbol::@18 u
union Object::@54 u
uint32_t nrnran123_get_globalindex()
Definition: nrnran123.cpp:24
Definition: section.h:132
#define NetParEventType
Definition: netcon.h:51
#define HocEventType
Definition: netcon.h:48
TQueue * net_cvode_instance_event_queue(NrnThread *)
Definition: netcvode.cpp:297
size_t q
Definition: hocdec.h:176
static void set_info(TQItem *tqi, int tid, NrnCoreTransferEvents *core_te, std::unordered_map< NetCon *, std::vector< size_t > > &netcon2intdata, std::unordered_map< PreSyn *, std::vector< size_t > > &presyn2intdata, std::unordered_map< double *, std::vector< size_t > > &weight2intdata)
double * _actual_b
Definition: multicore.h:73
return NULL
Definition: cabcode.cpp:461
int ndiam
Definition: cell_group.h:30
int * netcon_pntindex
Definition: cell_group.h:45
#define pdata
Definition: md1redef.h:28
TQItem * next(TQItem *)
Definition: sptbinq.cpp:366
double * _actual_v
Definition: multicore.h:74
short index
Definition: cabvars.h:11
int n_real_output
Definition: cell_group.h:29
int ith_
Definition: vrecitem.h:81
int nrn_is_ion(int)
Definition: eion.cpp:45
int n_netcon
Definition: cell_group.h:37
Point_process * target_
Definition: netcon.h:150
double delay_
Definition: netcon.h:263
IvocVect * discon_indices_
Definition: vrecitem.h:249
struct Prop * prop
Definition: section.h:151
Memb_list ** type2ml
Definition: cell_group.h:24
HocStruct Symbol * first
Definition: hocdec.h:85
int secondorder
Definition: init.cpp:120
#define TstopEventType
Definition: netcon.h:44