NEURON
cell_group.cpp
Go to the documentation of this file.
1 #include "cell_group.h"
3 #include "nrnran123.h" // globalindex written to globals.dat
4 #include "section.h"
5 #include "parse.hpp"
6 #include "nrnmpi.h"
7 #include "netcon.h"
8 
9 #include <limits>
10 #include <sstream>
11 
12 extern short* nrn_is_artificial_;
13 extern bool corenrn_direct;
14 extern int* bbcore_dparam_size;
16 extern int nrn_has_net_event_cnt_;
17 extern int* nrn_has_net_event_;
18 extern short* nrn_is_artificial_;
19 
23 
26  group_id = -1;
28  netcons = 0; output_ps = 0;
29  ndiam = 0;
31  datumindices = 0;
33  for (int i=0; i < n_memb_func; ++i) {
34  type2ml[i] = 0;
35  }
37 }
38 
40  if (output_gid) delete [] output_gid;
41  if (output_vindex) delete [] output_vindex;
42  if (netcon_srcgid) delete [] netcon_srcgid;
43  if (netcon_pnttype) delete [] netcon_pnttype;
44  if (netcon_pntindex) delete [] netcon_pntindex;
45  if (datumindices) delete [] datumindices;
46  if (netcons) delete [] netcons;
47  if (output_ps) delete [] output_ps;
48  if (ml_vdata_offset) delete [] ml_vdata_offset;
49  delete [] type2ml;
50 }
51 
52 
53 
55  for (int i = 0; i < nrn_nthread; ++i) {
56  int ncell = nrn_threads[i].ncell; // real cell count
57  int npre = ncell;
58  MlWithArt &mla = cgs[i].mlwithart;
59  for (size_t j = 0; j < mla.size(); ++j) {
60  int type = mla[j].first;
61  Memb_list *ml = mla[j].second;
62  cgs[i].type2ml[type] = ml;
63  if (nrn_has_net_event(type)) {
64  npre += ml->nodecount;
65  }
66  }
67  cgs[i].n_presyn = npre;
68  cgs[i].n_real_output = ncell;
69  cgs[i].output_ps = new PreSyn *[npre];
70  cgs[i].output_gid = new int[npre];
71  cgs[i].output_vindex = new int[npre];
72  // in case some cells do not have voltage presyns (eg threshold detection
73  // computed from a POINT_PROCESS NET_RECEIVE with WATCH and net_event)
74  // initialize as unused.
75  for (int j = 0; j < npre; ++j) {
76  cgs[i].output_ps[j] = NULL;
77  cgs[i].output_gid[j] = -1;
78  cgs[i].output_vindex[j] = -1;
79  }
80 
81  // fill in the artcell info
82  npre = ncell;
83  cgs[i].n_output = ncell; // add artcell (and PP with net_event) with gid in following loop
84  for (size_t j = 0; j < mla.size(); ++j) {
85  int type = mla[j].first;
86  Memb_list *ml = mla[j].second;
87  if (nrn_has_net_event(type)) {
88  for (int j = 0; j < ml->nodecount; ++j) {
89  Point_process *pnt = (Point_process *) ml->pdata[j][1]._pvoid;
90  PreSyn *ps = (PreSyn *) pnt->presyn_;
91  cgs[i].output_ps[npre] = ps;
92  long agid = -1;
93  if (nrn_is_artificial_[type]) {
94  // static_cast<long> ensures the RHS is calculated with
95  // `long` precision, not `int` precision. This lets us
96  // check for overflow below.
97  agid = -(type +
98  1000 * static_cast<long>(nrncore_art2index(pnt->prop->param)));
99  } else { // POINT_PROCESS with net_event
100  int sz = nrn_prop_param_size_[type];
101  double *d1 = ml->data[0];
102  double *d2 = pnt->prop->param;
103  assert(d2 >= d1 && d2 < (d1 + (sz * ml->nodecount)));
104  long ix{(d2 - d1) / sz};
105  agid = -(type + 1000 * ix);
106  }
107  if (ps) {
108  if (ps->output_index_ >= 0) { // has gid
109  cgs[i].output_gid[npre] = ps->output_index_;
110  if (cgs[i].group_id < 0) {
111  cgs[i].group_id = ps->output_index_;
112  }
113  ++cgs[i].n_output;
114  } else {
115  cgs[i].output_gid[npre] = agid;
116  }
117  } else { // if an acell is never a source, it will not have a presyn
118  cgs[i].output_gid[npre] = -1;
119  }
120  // the way we associate an acell PreSyn with the
121  // Point_process.
122  if (agid < std::numeric_limits<int>::min() || agid >= -1) {
123  std::ostringstream oss;
124  oss << "maximum of ~" << std::numeric_limits<int>::max() / 1000
125  << " artificial cells of a given type can be created per NrnThread, "
126  "this model has "
127  << ml->nodecount << " instances of " << memb_func[type].sym->name
128  << " (cannot store cgs[" << i << "].output_vindex[" << npre
129  << "]=" << agid << ')';
130  hoc_execerror("integer overflow", oss.str().c_str());
131  }
132  cgs[i].output_vindex[npre] = agid;
133  ++npre;
134  }
135  }
136  }
137  }
138  // work at netpar.cpp because we don't have the output gid hash tables here.
139  // fill in the output_ps, output_gid, and output_vindex for the real cells.
141 
142  // use first real cell gid, if it exists, as the group_id
143  if (corenrn_direct == false)
144  for (int i = 0; i < nrn_nthread; ++i) {
145  if (cgs[i].n_real_output && cgs[i].output_gid[0] >= 0) {
146  cgs[i].group_id = cgs[i].output_gid[0];
147  } else if (cgs[i].group_id >= 0) {
148  // set above to first artificial cell with a ps->output_index >= 0
149  } else {
150  // Don't die yet as the thread may be empty. That just means no files
151  // output for this thread and no mention in files.dat.
152  // Can check for empty near end of datatransform(CellGroup* cgs)
153  }
154  }
155 
156  // use the Hoc NetCon object list to segregate according to threads
157  // and fill the CellGroup netcons, netcon_srcgid, netcon_pnttype, and
158  // netcon_pntindex (and, if nrn_nthread > 1, netcon_negsrcgid_tid).
160 
161  return cgs;
162 }
163 
165  // ions, area, and POINTER to v or mechanism data.
166  for (int ith=0; ith < nrn_nthread; ++ith) {
167  NrnThread& nt = nrn_threads[ith];
168  CellGroup& cg = cgs[ith];
169  // how many mechanisms in use and how many DatumIndices do we need.
170  MlWithArt& mla = cgs[ith].mlwithart;
171  for (size_t j = 0; j < mla.size(); ++j) {
172  Memb_list* ml = mla[j].second;
173  ++cg.n_mech;
174  if (ml->pdata[0]) {
175  ++cg.ntype;
176  }
177  }
178  cg.datumindices = new DatumIndices[cg.ntype];
179  // specify type, allocate the space, and fill the indices
180  int i=0;
181  for (size_t j = 0; j < mla.size(); ++j) {
182  int type = mla[j].first;
183  Memb_list* ml = mla[j].second;
184  int sz = bbcore_dparam_size[type];
185  if (sz) {
186  DatumIndices& di = cg.datumindices[i++];
187  di.type = type;
188  int n = ml->nodecount * sz;
189  di.ion_type = new int[n];
190  di.ion_index = new int[n];
191  // fill the indices.
192  // had tointroduce a memb_func[i].dparam_semantics registered by each mod file.
193  datumindex_fill(ith, cg, di, ml);
194  }
195  }
196  // if model is being transferred via files, and
197  // if there are no gids in the thread (group_id < 0), and
198  // if the thread is not empty (mechanisms exist, n_mech > 0)
199  if (corenrn_direct == false && cg.group_id < 0 && cg.n_mech > 0) {
200  hoc_execerror("A nonempty thread has no real cell or ARTIFICIAL_CELL with a gid", NULL);
201  }
202  }
203 }
204 
205 
206 
208  NrnThread& nt = nrn_threads[ith];
209  double* a = nt._actual_area;
210  int nnode = nt.end;
211  int mcnt = ml->nodecount;
212  int dsize = bbcore_dparam_size[di.type];
213  if (dsize == 0) { return; }
214  int* dmap = memb_func[di.type].dparam_semantics;
215  assert(dmap);
216  // what is the size of the nt._vdata portion needed for a single ml->dparam[i]
217  int vdata_size = 0;
218  for (int i=0; i < dsize; ++i) {
219  int* ds = memb_func[di.type].dparam_semantics;
220  if (ds[i] == -4 || ds[i] == -6 || ds[i] == -7 || ds[i] == 0) {
221  ++vdata_size;
222  }
223  }
224 
225  int isart = nrn_is_artificial_[di.type];
226  for (int i=0; i < mcnt; ++i) {
227  // Prop* datum instance arrays are not in cache efficient order
228  // ie. ml->pdata[i] are not laid out end to end in memory.
229  // Also, ml->data for artificial cells is not in cache efficient order
230  // but in the artcell case there are no pointers to doubles and
231  // the _actual_area pointer should be left unfilled.
232  Datum* dparam = ml->pdata[i];
233  int offset = i*dsize;
234  int vdata_offset = i*vdata_size;
235  for (int j=0; j < dsize; ++j) {
236  int etype = -100; // uninterpreted
237  int eindex = -1;
238  if (dmap[j] == -1) { // double* into _actual_area
239  if (isart) {
240  etype = -1;
241  eindex = -1; // the signal to ignore in bbcore.
242  }else{
243  if (dparam[j].pval == &ml->nodelist[i]->_area) {
244  // possibility it points directly into Node._area instead of
245  // _actual_area. For our purposes we need to figure out the
246  // _actual_area index.
247  etype = -1;
248  eindex = ml->nodeindices[i];
249  assert(a[ml->nodeindices[i]] == *dparam[j].pval);
250  }else{
251  if (dparam[j].pval < a || dparam[j].pval >= (a + nnode)){
252  printf("%s dparam=%p a=%p a+nnode=%p j=%d\n",
253  memb_func[di.type].sym->name, dparam[j].pval, a, a+nnode, j);
254  abort();
255  }
256  assert(dparam[j].pval >= a && dparam[j].pval < (a + nnode));
257  etype = -1;
258  eindex = dparam[j].pval - a;
259  }
260  }
261  }else if (dmap[j] == -2) { // this is an ion and dparam[j][0].i is the iontype
262  etype = -2;
263  eindex = dparam[j].i;
264  }else if (dmap[j] == -3) { // cvodeieq is always last and never seen
265  assert(dmap[j] != -3);
266  }else if (dmap[j] == -4) { // netsend (_tqitem pointer)
267  // eventually index into nt->_vdata
268  etype = -4;
269  eindex = vdata_offset++;
270  }else if (dmap[j] == -6) { // pntproc
271  // eventually index into nt->_vdata
272  etype = -6;
273  eindex = vdata_offset++;
274  }else if (dmap[j] == -7) { // bbcorepointer
275  // eventually index into nt->_vdata
276  etype = -6;
277  eindex = vdata_offset++;
278  }else if (dmap[j] == -8) { // watch
279  etype = -8;
280  eindex = 0;
281  }else if (dmap[j] == -10) { // fornetcon
282  etype = -10;
283  eindex = 0;
284  }else if (dmap[j] == -9) { // diam
285  cg.ndiam = nt.end;
286  etype = -9;
287  // Rare for a mechanism to use dparam pointing to diam.
288  // MORPHOLOGY was never made cache efficient. And
289  // is not in the tml_with_art.
290  // Need to determine this node and then simple to search its
291  // mechanism list for MORPHOLOGY and then know the diam.
292  Node* nd = ml->nodelist[i];
293  double* pdiam = NULL;
294  for (Prop* p = nd->prop; p; p = p->next) {
295  if (p->type == MORPHOLOGY) {
296  pdiam = p->param;
297  break;
298  }
299  }
300  assert(dparam[j].pval == pdiam);
301  eindex = ml->nodeindices[i];
302  }else if (dmap[j] == -5) { // POINTER
303  // must be a pointer into nt->_data. Handling is similar to eion so
304  // give proper index into the type.
305  double* pd = dparam[j].pval;
306  nrn_dblpntr2nrncore(pd, nt, etype, eindex);
307  if (etype == 0) {
308  fprintf(stderr, "POINTER is not pointing to voltage or mechanism data. Perhaps it should be a BBCOREPOINTER\n");
309  }
310  assert(etype != 0);
311  // pointer into one of the tml types?
312  }else if (dmap[j] > 0 && dmap[j] < 1000) { // double* into eion type data
313  Memb_list* eml = cg.type2ml[dmap[j]];
314  assert(eml);
315  if(dparam[j].pval < eml->data[0]){
316  printf("%s dparam=%p data=%p j=%d etype=%d %s\n",
317  memb_func[di.type].sym->name, dparam[j].pval, eml->data[0], j,
318  dmap[j], memb_func[dmap[j]].sym->name);
319  abort();
320  }
321  assert(dparam[j].pval >= eml->data[0]);
322  etype = dmap[j];
323  if (dparam[j].pval >= (eml->data[0] +
324  (nrn_prop_param_size_[etype] * eml->nodecount))) {
325  printf("%s dparam=%p data=%p j=%d psize=%d nodecount=%d etype=%d %s\n",
326  memb_func[di.type].sym->name, dparam[j].pval, eml->data[0], j,
327  nrn_prop_param_size_[etype],
328  eml->nodecount, etype, memb_func[etype].sym->name);
329  }
330  assert(dparam[j].pval < (eml->data[0] +
331  (nrn_prop_param_size_[etype] * eml->nodecount)));
332  eindex = dparam[j].pval - eml->data[0];
333  }else if (dmap[j] > 1000) {//int* into ion dparam[xxx][0]
334  //store the actual ionstyle
335  etype = dmap[j];
336  eindex = *((int*)dparam[j]._pvoid);
337  } else {
338  char errmes[100];
339  sprintf(errmes, "Unknown semantics type %d for dparam item %d of", dmap[j], j);
340  hoc_execerror(errmes, memb_func[di.type].sym->name);
341  }
342  di.ion_type[offset + j] = etype;
343  di.ion_index[offset + j] = eindex;
344  }
345  }
346 }
347 
348 
349 
350 // use the Hoc NetCon object list to segregate according to threads
351 // and fill the CellGroup netcons, netcon_srcgid, netcon_pnttype, and
352 // netcon_pntindex (called at end of mk_cellgroups);
354  // count the netcons for each thread
355  int* nccnt = new int[nrn_nthread];
356  for (int i=0; i < nrn_nthread; ++i) {
357  nccnt[i] = 0;
358  }
359  Symbol* ncsym = hoc_lookup("NetCon");
360  hoc_List* ncl = ncsym->u.ctemplate->olist;
361  hoc_Item* q;
362  ITERATE(q, ncl) {
363  Object* ho = (Object*)VOIDITM(q);
364  NetCon* nc = (NetCon*)ho->u.this_pointer;
365  int ith = 0; // if no _vnt, put in thread 0
366  if (nc->target_ && nc->target_->_vnt) {
367  ith = ((NrnThread*)(nc->target_->_vnt))->id;
368  }
369  ++nccnt[ith];
370  }
371 
372  // allocate
373  for (int i=0; i < nrn_nthread; ++i) {
374  cgs[i].n_netcon = nccnt[i];
375  cgs[i].netcons = new NetCon*[nccnt[i]+1];
376  cgs[i].netcon_srcgid = new int[nccnt[i]+1];
377  cgs[i].netcon_pnttype = new int[nccnt[i]+1];
378  cgs[i].netcon_pntindex = new int[nccnt[i]+1];
379  }
380 
381  // reset counts and fill
382  for (int i=0; i < nrn_nthread; ++i) {
383  nccnt[i] = 0;
384  }
385  ITERATE(q, ncl) {
386  Object* ho = (Object*)VOIDITM(q);
387  NetCon* nc = (NetCon*)ho->u.this_pointer;
388  int ith = 0; // if no _vnt, put in thread 0
389  if (nc->target_ && nc->target_->_vnt) {
390  ith = ((NrnThread*)(nc->target_->_vnt))->id;
391  }
392  int i = nccnt[ith];
393  cgs[ith].netcons[i] = nc;
394 
395  if (nc->target_) {
396  int type = nc->target_->prop->type;
397  cgs[ith].netcon_pnttype[i] = type;
398  if (nrn_is_artificial_[type]) {
400  }else{
401  // cache efficient so can calculate index from pointer
402  Memb_list* ml = cgs[ith].type2ml[type];
403  int sz = nrn_prop_param_size_[type];
404  double* d1 = ml->data[0];
405  double* d2 = nc->target_->prop->param;
406  assert(d2 >= d1 && d2 < (d1 + (sz*ml->nodecount)));
407  int ix = (d2 - d1)/sz;
408  cgs[ith].netcon_pntindex[i] = ix;
409  }
410  }else{
411  cgs[ith].netcon_pnttype[i] = 0;
412  cgs[ith].netcon_pntindex[i] = -1;
413  }
414 
415  if (nc->src_) {
416  PreSyn* ps = nc->src_;
417  if (ps->gid_ >= 0) {
418  cgs[ith].netcon_srcgid[i] = ps->gid_;
419  }else{
420  if (ps->osrc_) {
421  assert(ps->thvar_ == NULL);
422  if (nrn_nthread > 1) { // negative gid and multiple threads.
423  cgs[ith].netcon_negsrcgid_tid.push_back(ps->nt_->id);
424  // Raise error if file mode transfer and nc and ps not
425  // in same thread. In that case we cannot guarantee that
426  // the PreSyn will end up in the same coreneuron process.
427  if (!corenrn_direct && ith != ps->nt_->id) {
428  hoc_execerror("NetCon and NetCon source with no gid are not in the same thread", NULL);
429  }
430  }
432  int type = pnt->prop->type;
434  int ix = nrncore_art2index(pnt->prop->param);
435  cgs[ith].netcon_srcgid[i] = -(type + 1000*ix);
436  }else{
437  assert(nrn_has_net_event(type));
438  Memb_list* ml = cgs[ith].type2ml[type];
439  int sz = nrn_prop_param_size_[type];
440  double* d1 = ml->data[0];
441  double* d2 = pnt->prop->param;
442  assert(d2 >= d1 && d2 < (d1 + (sz*ml->nodecount)));
443  int ix = (d2 - d1)/sz;
444  cgs[ith].netcon_srcgid[i] = -(type + 1000*ix);
445  }
446  }else{
447  cgs[ith].netcon_srcgid[i] = -1;
448  }
449  }
450  }else{
451  cgs[ith].netcon_srcgid[i] = -1;
452  }
453  ++nccnt[ith];
454  }
455  delete [] nccnt;
456 }
457 
458 
459 // Up to now all the artificial cells have been left out of the processing.
460 // Since most processing is in the context of iteration over nt.tml it
461 // might be easiest to transform the loops using a
462 // copy of nt.tml with artificial cell types belonging to nt at the end.
463 // Treat these artificial cell memb_list as much as possible like the others.
464 // The only issue is that data for artificial cells is not in cache order
465 // (after all there is no BREAKPOINT or SOLVE block for ARTIFICIAL_CELLs)
466 // so we assume there will be no POINTER usage into that data.
467 // Also, note that ml.nodecount for artificial cell does not refer to
468 // a list of voltage nodes but just to the count of instances.
470  // copy NrnThread tml list and append ARTIFICIAL cell types
471  // but do not include PatternStim if file mode.
472  // For direct mode PatternStim is not treated specially except that
473  // the Info struct is shared.
474  // For file mode transfer PatternStim has always been treated
475  // specially by CoreNEURON as it is not conceptually a part of
476  // the model but is invoked via an argument when launching
477  // CoreNEURON from the shell.
478  // Now using cgs[tid].mlwithart instead of
479  // tml_with_art = new NrnThreadMembList*[nrn_nthread];
480  // to allow fast retrieval of type and Memb_list* given index into the vector.
481 
482  // copy from NrnThread
483  for (int id = 0; id < nrn_nthread; ++id) {
484  MlWithArt& mla = cgs[id].mlwithart;
485  for (NrnThreadMembList* tml = nrn_threads[id].tml; tml; tml = tml->next) {
486  mla.push_back(MlWithArtItem(tml->index, tml->ml));
487  }
488  }
489  int *acnt = new int[nrn_nthread];
490 
491  for (int i = 0; i < n_memb_func; ++i) {
493  // skip PatternStim if file mode transfer.
494  if (!corenrn_direct && strcmp(memb_func[i].sym->name, "PatternStim") == 0) {
495  continue;
496  }
497  if (strcmp(memb_func[i].sym->name, "HDF5Reader") == 0) { continue; }
498  Memb_list* ml = memb_list + i;
499  // how many artificial in each thread
500  for (int id = 0; id < nrn_nthread; ++id) {acnt[id] = 0;}
501  for (int j = 0; j < memb_list[i].nodecount; ++j) {
502  Point_process* pnt = (Point_process*)memb_list[i].pdata[j][1]._pvoid;
503  int id = ((NrnThread*)pnt->_vnt)->id;
504  ++acnt[id];
505  }
506 
507  // allocate
508  for (int id = 0; id < nrn_nthread; ++id) {
509  if (acnt[id]) {
510  MlWithArt& mla = cgs[id].mlwithart;
511  ml = new Memb_list;
512  mla.push_back(MlWithArtItem(i, ml)); // need to delete ml when mla destroyed.
513  ml->nodecount = acnt[id];
514  ml->nodelist = NULL;
515  ml->nodeindices = NULL;
516  ml->prop = NULL;
517  ml->_thread = NULL;
518  ml->data = new double*[acnt[id]];
519  ml->pdata = new Datum*[acnt[id]];
520  }
521  }
522  // fill data and pdata pointers
523  // and fill the artdata2index hash table
524  for (int id = 0; id < nrn_nthread; ++id) {acnt[id] = 0;}
525  for (int j = 0; j < memb_list[i].nodecount; ++j) {
526  Point_process* pnt = (Point_process*)memb_list[i].pdata[j][1]._pvoid;
527  int id = ((NrnThread*)pnt->_vnt)->id;
528  Memb_list* ml = cgs[id].mlwithart.back().second;
529  ml->data[acnt[id]] = memb_list[i].data[j];
530  ml->pdata[acnt[id]] = memb_list[i].pdata[j];
531  artdata2index_.insert(std::pair<double*, int>(ml->data[acnt[id]], acnt[id]));
532  ++acnt[id];
533  }
534  }
535  }
536  delete [] acnt;
537 }
538 
540  size_t mla_rankbytes=0;
541  size_t nbytes;
542  NrnThread* nt;
543  NrnThreadMembList* tml;
544  FOR_THREADS(nt)
545  {
546  size_t threadbytes = 0;
547  size_t npnt = 0;
548  size_t nart = 0;
549  int ith = nt->id;
550  //printf("rank %d thread %d\n", nrnmpi_myid, ith);
551  //printf(" ncell=%d nnode=%d\n", nt->ncell, nt->end);
552  //v_parent_index, _actual_a, _actual_b, _actual_area
553  nbytes = nt->end * (1 * sizeof(int) + 3 * sizeof(double));
554  threadbytes += nbytes;
555 
556  int mechcnt = 0;
557  size_t mechcnt_instances = 0;
558  MlWithArt &mla = cellgroups_[ith].mlwithart;
559  for (size_t i = 0; i < mla.size(); ++i) {
560  int type = mla[i].first;
561  Memb_list *ml = mla[i].second;
562  ++mechcnt;
563  mechcnt_instances += ml->nodecount;
564  npnt += (memb_func[type].is_point ? ml->nodecount : 0);
565  int psize = nrn_prop_param_size_[type];
566  int dpsize = nrn_prop_dparam_size_[type]; // includes cvodeieq if present
567  //printf("%d %s ispnt %d cnt %d psize %d dpsize %d\n",tml->index, memb_func[type].sym->name,
568  //memb_func[type].is_point, ml->nodecount, psize, dpsize);
569  // nodeindices, data, pdata + pnt with prop
570  int notart = nrn_is_artificial_[type] ? 0 : 1;
571  if (nrn_is_artificial_[type]) {
572  nart += ml->nodecount;
573  }
574  nbytes = ml->nodecount * (notart * sizeof(int) + 1 * sizeof(double *) +
575  1 * sizeof(Datum * ) + psize * sizeof(double) + dpsize * sizeof(Datum));
576  threadbytes += nbytes;
577  }
578  nbytes += npnt * (sizeof(Point_process) + sizeof(Prop));
579  //printf(" mech in use %d Point instances %ld artcells %ld total instances %ld\n",
580  //mechcnt, npnt, nart, mechcnt_instances);
581  //printf(" thread bytes %ld\n", threadbytes);
582  mla_rankbytes += threadbytes;
583  }
584  return mla_rankbytes;
585 }
586 
588  // clean up the art Memb_list of CellGroup[].mlwithart
589  // But if multithread and direct transfer mode, defer deletion of
590  // data for artificial cells, so that the artificial cell ml->data
591  // can be used when nrnthreads_type_return is called.
592  if (corenrn_direct && nrn_nthread > 0) {
594  }
595  for (int ith=0; ith < nrn_nthread; ++ith) {
596  MlWithArt& mla = cgs[ith].mlwithart;
597  for (size_t i = 0; i < mla.size(); ++i) {
598  int type = mla[i].first;
599  Memb_list* ml = mla[i].second;
600  if (nrn_is_artificial_[type]) {
601  if (!deferred_type2artml_.empty()) {
602  deferred_type2artml_[ith][type] = ml;
603  }else{
604  delete [] ml->data;
605  delete [] ml->pdata;
606  delete ml;
607  }
608  }
609  }
610  }
611 }
612 
614  if (has_net_event_) {
615  return;
616  }
617 
618  has_net_event_ = new int[n_memb_func];
619  for (int i=0; i < n_memb_func; ++i) {
620  has_net_event_[i] = 0;
621  }
622  for(int i=0; i < nrn_has_net_event_cnt_; ++i) {
624  }
625 }
#define data
Definition: rbtqueue.cpp:49
static int nrn_has_net_event(int type)
Definition: cell_group.h:91
int n_output
Definition: cell_group.h:28
FOR_THREADS(_nt)
Definition: multicore.cpp:887
static Deferred_Type2ArtMl deferred_type2artml_
Definition: cell_group.h:76
struct Memb_list Memb_list
double max(double a, double b)
Definition: geometry3d.cpp:22
double * param
Definition: section.h:218
static void datumindex_fill(int, CellGroup &, DatumIndices &, Memb_list *)
Definition: cell_group.cpp:207
#define assert(ex)
Definition: hocassrt.h:26
short type
Definition: cabvars.h:10
static void datumtransform(CellGroup *)
Definition: cell_group.cpp:164
void * _vnt
Definition: section.h:269
static void clean_art(CellGroup *)
Definition: cell_group.cpp:587
void * _pvoid
Definition: hocdec.h:186
std::vector< MlWithArtItem > MlWithArt
Definition: cell_group.h:16
Definition: netcon.h:232
int group_id
Definition: cell_group.h:25
if(status)
struct Point_process Point_process
#define min(a, b)
Definition: matrix.h:157
int * ml_vdata_offset
Definition: cell_group.h:32
int nrn_dblpntr2nrncore(double *pd, NrnThread &nt, int &type, int &index)
#define ITERATE(itm, lst)
Definition: model.h:25
double * pval
Definition: hocdec.h:180
NrnThread * nt_
Definition: netcon.h:270
std::map< double *, int > PVoid2Int
Definition: cell_group.h:17
Symbol * hoc_lookup(const char *)
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
char * name
Definition: model.h:72
Memb_func * memb_func
Definition: init.cpp:161
nd
Definition: treeset.cpp:893
Object * osrc_
Definition: netcon.h:265
Point_process * target_
Definition: netcon.h:106
double ** data
Definition: nrnoc_ml.h:14
int * bbcore_dparam_size
int i
Definition: hocdec.h:179
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
Prop ** prop
Definition: nrnoc_ml.h:16
#define MORPHOLOGY
Definition: membfunc.h:63
hoc_List * olist
Definition: hocdec.h:203
Datum * _thread
Definition: nrnoc_ml.h:17
PreSyn * src_
Definition: netcon.h:105
j< sec-> nnode
Definition: treeset.cpp:905
MlWithArt mlwithart
Definition: cell_group.h:49
short type
Definition: section.h:215
int id
Definition: multicore.h:66
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
bool corenrn_direct
Symbol * sym
Definition: membfunc.h:38
int nrn_nthread
Definition: multicore.cpp:44
static void mk_tml_with_art(CellGroup *)
Definition: cell_group.cpp:469
void * presyn_
Definition: section.h:267
int const size_t const size_t n
Definition: nrngsl.h:12
int nodecount
Definition: nrnoc_ml.h:18
static int nrncore_art2index(double *d)
Definition: cell_group.h:86
NrnThread * nrn_threads
Definition: multicore.cpp:45
Memb_list * memb_list
Definition: init.cpp:162
Prop * prop
Definition: section.h:264
#define printf
Definition: mwprefix.h:26
NetCon ** netcons
Definition: cell_group.h:38
#define VOIDITM(q)
Definition: hoclist.h:68
int
Definition: nrnmusic.cpp:71
CellGroup * cellgroups_
int n_memb_func
Definition: init.cpp:471
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
double * thvar_
Definition: netcon.h:264
size_t j
Datum ** pdata
Definition: nrnoc_ml.h:15
fprintf(stderr, "Don't know the location of params at %p\, pp)
Definition: model.h:57
static void mk_cgs_netcon_info(CellGroup *cgs)
Definition: cell_group.cpp:353
int * output_gid
Definition: cell_group.h:35
Definition: section.h:213
int n_mech
Definition: cell_group.h:31
static CellGroup * mk_cellgroups(CellGroup *)
Definition: cell_group.cpp:54
PreSyn ** output_ps
Definition: cell_group.h:34
Definition: netcon.h:82
int n_presyn
Definition: cell_group.h:27
int * nrn_prop_param_size_
Definition: init.cpp:178
virtual ~CellGroup()
Definition: cell_group.cpp:39
int gid_
Definition: netcon.h:277
short * nrn_is_artificial_
Definition: cell_group.cpp:18
static size_t get_mla_rankbytes(CellGroup *)
Definition: cell_group.cpp:539
int * nrn_prop_dparam_size_
Definition: init.cpp:179
int end
Definition: multicore.h:65
int * netcon_srcgid
Definition: cell_group.h:39
VEC * cgs(MTX_FN A, void *A_params, VEC *b, VEC *r0, double tol, VEC *x)
Definition: conjgrad.c:179
union Datum Datum
Node ** nodelist
Definition: nrnoc_ml.h:5
std::vector< int > netcon_negsrcgid_tid
Definition: cell_group.h:41
Definition: hocdec.h:226
HocStruct cTemplate * ctemplate
Definition: hocdec.h:151
#define nodecount
Definition: md1redef.h:30
#define i
Definition: md1redef.h:12
int is_point
Definition: membfunc.h:53
#define id
Definition: md1redef.h:33
int nrn_has_net_event_cnt_
Definition: init.cpp:176
double _area
Definition: section.h:140
double * _actual_area
Definition: multicore.h:75
int * dparam_semantics
Definition: membfunc.h:56
int * nrn_has_net_event_
Definition: init.cpp:177
union Symbol::@18 u
int ntype
Definition: cell_group.h:47
void nrncore_netpar_cellgroups_helper(CellGroup *)
Definition: netpar.cpp:1567
union Object::@54 u
Definition: section.h:132
size_t q
Definition: hocdec.h:176
#define pval
Definition: md1redef.h:32
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
static PVoid2Int artdata2index_
Definition: cell_group.h:82
static void setup_nrn_has_net_event()
Definition: cell_group.cpp:613
static int * has_net_event_
Definition: cell_group.h:84
int n_real_output
Definition: cell_group.h:29
int n_netcon
Definition: cell_group.h:37
std::vector< std::map< int, Memb_list * > > Deferred_Type2ArtMl
Definition: cell_group.h:18
struct Prop * prop
Definition: section.h:151
Memb_list ** type2ml
Definition: cell_group.h:24