@@ -113,6 +113,14 @@ void (*nrn2core_all_weights_return_)(std::vector<double*>& weights);
113113// encode the thread number into the negative gid
114114// (i.e -ith - nth*(type +1000*index)) failed due to not large enough
115115// integer domain size.
116+ // Note that for file transfer it is an error if a negative srcgid is
117+ // not in the same thread as the target. This is because there it may
118+ // not be the case that threads in a NEURON process end up on same process
119+ // in CoreNEURON. NEURON will raise an error if this
120+ // is the case. However, for direct memory transfer, it is allowed that
121+ // a negative srcgid may be in a different thread than the target. So
122+ // nrn2core_get_dat1 has a last arg netcon_negsrcgid_tid that specifies
123+ // for the negative gids in netcon_srcgid (in that order) the source thread.
116124//
117125// <firstgid>_2.dat
118126// n_output n_real_output, nnode
@@ -178,7 +186,11 @@ std::map<int, InputPreSyn*> gid2in;
178186std::vector<NetCon*> netcon_in_presyn_order_;
179187
180188// / Only for setup vector of netcon source gids
181- std::vector<int *> netcon_srcgid;
189+ std::vector<int *> nrnthreads_netcon_srcgid;
190+
191+ // / If a nrnthreads_netcon_srcgid is negative, need to determine the thread when
192+ // / in order to use the correct neg_gid2out[tid] map
193+ std::vector<std::vector<int > > nrnthreads_netcon_negsrcgid_tid;
182194
183195/* read files.dat file and distribute cellgroups to all mpi ranks */
184196void nrn_read_filesdat (int & ngrp, int *& grp, const char * filesdat) {
@@ -275,8 +287,11 @@ void determine_inputpresyn() {
275287 NrnThread& nt = nrn_threads[ith];
276288 // associate gid with InputPreSyn and increase PreSyn and InputPreSyn count
277289 nt.n_input_presyn = 0 ;
290+ // if single thread or file transfer then definitely empty.
291+ std::vector<int >& negsrcgid_tid = nrnthreads_netcon_negsrcgid_tid[ith];
292+ size_t i_tid = 0 ;
278293 for (int i = 0 ; i < nt.n_netcon ; ++i) {
279- int gid = netcon_srcgid [ith][i];
294+ int gid = nrnthreads_netcon_srcgid [ith][i];
280295 if (gid >= 0 ) {
281296 // / If PreSyn or InputPreSyn is already in the map
282297 auto gid2out_it = gid2out.find (gid);
@@ -299,8 +314,12 @@ void determine_inputpresyn() {
299314 inputpresyn_.push_back (psi);
300315 ++nt.n_input_presyn ;
301316 } else {
302- auto gid2out_it = neg_gid2out[nt.id ].find (gid);
303- if (gid2out_it != neg_gid2out[nt.id ].end ()) {
317+ int tid = nt.id ;
318+ if (!negsrcgid_tid.empty ()) {
319+ tid = negsrcgid_tid[i_tid++];
320+ }
321+ auto gid2out_it = neg_gid2out[tid].find (gid);
322+ if (gid2out_it != neg_gid2out[tid].end ()) {
304323 // / Increase negative PreSyn count
305324 ++gid2out_it->second ->nc_cnt_ ;
306325 }
@@ -361,16 +380,23 @@ void determine_inputpresyn() {
361380
362381 // fill the netcon_in_presyn_order and recompute nc_cnt_
363382 // note that not all netcon_in_presyn will be filled if there are netcon
364- // with no presyn (ie. netcon_srcgid [nt.id][i] = -1) but that is ok since they are
383+ // with no presyn (ie. nrnthreads_netcon_srcgid [nt.id][i] = -1) but that is ok since they are
365384 // only used via ps.nc_index_ and ps.nc_cnt_;
366385 for (int ith = 0 ; ith < nrn_nthread; ++ith) {
367386 NrnThread& nt = nrn_threads[ith];
387+ // if single thread or file transfer then definitely empty.
388+ std::vector<int >& negsrcgid_tid = nrnthreads_netcon_negsrcgid_tid[ith];
389+ size_t i_tid = 0 ;
368390 for (int i = 0 ; i < nt.n_netcon ; ++i) {
369391 NetCon* nc = nt.netcons + i;
370- int gid = netcon_srcgid[ith][i];
392+ int gid = nrnthreads_netcon_srcgid[ith][i];
393+ int tid = ith;
394+ if (!negsrcgid_tid.empty () && gid < -1 ) {
395+ tid = negsrcgid_tid[i_tid++];
396+ }
371397 PreSyn* ps;
372398 InputPreSyn* psi;
373- netpar_tid_gid2ps (ith , gid, &ps, &psi);
399+ netpar_tid_gid2ps (tid , gid, &ps, &psi);
374400 if (ps) {
375401 netcon_in_presyn_order_[ps->nc_index_ + ps->nc_cnt_ ] = nc;
376402 ++ps->nc_cnt_ ;
@@ -390,10 +416,11 @@ void determine_inputpresyn() {
390416// / Clean up
391417void nrn_setup_cleanup () {
392418 for (int ith = 0 ; ith < nrn_nthread; ++ith) {
393- if (netcon_srcgid [ith])
394- delete[] netcon_srcgid [ith];
419+ if (nrnthreads_netcon_srcgid [ith])
420+ delete[] nrnthreads_netcon_srcgid [ith];
395421 }
396- netcon_srcgid.clear ();
422+ nrnthreads_netcon_srcgid.clear ();
423+ nrnthreads_netcon_negsrcgid_tid.clear ();
397424 neg_gid2out.clear ();
398425}
399426
@@ -448,9 +475,9 @@ void nrn_setup(const char* filesdat,
448475 // / std::map<int, PreSyn*> gid2out;
449476 gid2out.clear ();
450477
451- netcon_srcgid .resize (nrn_nthread);
478+ nrnthreads_netcon_srcgid .resize (nrn_nthread);
452479 for (int i = 0 ; i < nrn_nthread; ++i)
453- netcon_srcgid [i] = nullptr ;
480+ nrnthreads_netcon_srcgid [i] = nullptr ;
454481
455482 // gap junctions
456483 if (nrn_have_gaps) {
@@ -469,6 +496,7 @@ void nrn_setup(const char* filesdat,
469496 nrn_partrans::gap_mpi_setup (userParams.ngroup );
470497 }
471498
499+ nrnthreads_netcon_negsrcgid_tid.resize (nrn_nthread);
472500 if (!corenrn_embedded) {
473501 coreneuron::phase_wrapper<coreneuron::phase::one>(userParams);
474502 } else {
@@ -480,7 +508,7 @@ void nrn_setup(const char* filesdat,
480508 });
481509 }
482510
483- // from the gid2out map and the netcon_srcgid array,
511+ // from the gid2out map and the nrnthreads_netcon_srcgid array,
484512 // fill the gid2in, and from the number of entries,
485513 // allocate the process wide InputPreSyn array
486514 determine_inputpresyn ();
0 commit comments