NEURON
nrnmusic.cpp
Go to the documentation of this file.
1 #define NO_PYTHON_H 1
2 #include <../neuronmusic/nrnmusic.h>
3 #include <unordered_map>
4 
5 extern int nrnmusic;
6 extern MPI_Comm nrnmusic_comm;
7 
8 void nrnmusic_init(int*, char***);
9 void nrnmusic_terminate();
10 
11 void nrnmusic_injectlist(void* vp, double tt);
12 void nrnmusic_inject(void* port, int gindex, double tt);
13 void nrnmusic_spikehandle(void* vport, double tt, int gindex);
14 
15 extern Object* nrnpy_po2ho(PyObject*);
16 extern PyObject* nrnpy_ho2po(Object*);
17 extern Object* hoc_new_object(Symbol*, void*);
18 
19 MUSIC::Setup* nrnmusic_setup;
20 MUSIC::Runtime* nrnmusic_runtime;
21 
22 class NrnMusicEventHandler: public MUSIC::EventHandlerLocalIndex {
23  public:
24  void operator()(double t, MUSIC::LocalIndex id);
27 };
28 
30  public:
31  MusicPortPair(void* port, int gindex, void* p);
32  virtual ~MusicPortPair();
33  void clear(); // avoid recursion on delete by first calling clear
34  void* port_;
35  int gindex_;
37 };
38 MusicPortPair::MusicPortPair(void* port, int gindex, void* vp) {
39  port_ = port;
40  gindex_ = gindex;
41  next_ = (MusicPortPair*) vp;
42 }
44  if (next_) {
45  delete next_;
46  }
47 }
49  MusicPortPair *i, *j;
50  for (i = next_; i; i = j) {
51  j = i->next_;
52  i->next_ = 0;
53  delete i;
54  }
55 }
56 
58  public:
60  virtual ~NetParMusicEvent();
61  virtual void send(double, NetCvode*, NrnThread*);
62  virtual void deliver(double, NetCvode*, NrnThread*);
63  virtual int type() {
64  return 100;
65  }
66 };
68 
69 using PortTable = std::unordered_map<void*, int>;
72 
75 void NetParMusicEvent::send(double t, NetCvode* nc, NrnThread* nt) {
76  nc->event(t + usable_mindelay_, this, nt);
77 }
79  nrnmusic_runtime->tick();
80  send(t, nc, nt);
81 }
82 
84  if (music_input_ports) {
85  return;
86  }
89 }
90 
91 void nrnmusic_injectlist(void* vp, double tt) {
92  MusicPortPair* mpp;
93  for (mpp = (MusicPortPair*) vp; mpp; mpp = mpp->next_) {
94  nrnmusic_inject(mpp->port_, mpp->gindex_, tt);
95  }
96 }
97 
98 void nrnmusic_inject(void* vport, int gi, double tt) {
99  // printf("nrnmusic_inject %p %d %g\n", vport, gi, tt);
100  ((MUSIC::EventOutputPort*) vport)
101  ->insertEvent(tt / 1000.0, // unit conversion ms -> s
102  (MUSIC::GlobalIndex) gi);
103 }
104 
106  table = new PreSyn*[cnt];
107  int j = 0;
108  for (const auto& iter: *(port->gi_table)) {
109  PreSyn* ps = iter.second;
110  table[j] = ps;
111  ++j;
112  }
113 }
114 
115 void NrnMusicEventHandler::operator()(double t, MUSIC::LocalIndex id) {
116  PreSyn* ps = table[id];
117  ps->send(1000.0 * t, net_cvode_instance, nrn_threads);
118  // printf("event handler t=%g id=%d ps=%p\n", t, int(id), ps);
119 }
120 
123 }
124 
126  // analogous to pc.cell
127  // except pc.cell(gid, nc) has already been called and this
128  // will add this to the PreSyn.music_out_ list.
130  auto iter = gid2out_.find(gid);
131  if (iter == gid2out_.end()) {
132  return;
133  }
134  PreSyn* ps = iter->second;
135  ps->music_port_ = new MusicPortPair((void*) this, gi, ps->music_port_);
136 
137  // to create an IndexList for a later map, need to
138  // save the indices used for each port
139  int i = 0;
140  if (music_output_ports->count((void*) this) == 0) {
141  (*music_output_ports)[(void*) this] = i;
142  gi_table = new Gi2PreSynTable(1024);
143  }
144  nrn_assert(gi_table->count(gi) == 0);
145  // printf("gid2index insert %p %d\n", this, gi);
146  (*gi_table)[gi] = ps;
147 }
148 
149 NRNMUSIC::EventInputPort::EventInputPort(MUSIC::Setup* s, std::string id)
150  : MUSIC::Port(s, id)
151  , MUSIC::EventInputPort(s, id) {
152  gi_table = new Gi2PreSynTable(1024);
153 }
154 
157 }
158 
159 PyObject* NRNMUSIC::EventInputPort::index2target(int gi, PyObject* ptarget) {
160  // analogous to pc.gid_connect
161  Object* target = nrnpy_po2ho(ptarget);
162  if (!is_point_process(target)) {
163  hoc_execerror("target arg must be a Point_process", 0);
164  }
166  PreSyn* ps;
167  int i = 0;
168  if (music_input_ports->count((void*) this) == 0) {
169  (*music_input_ports)[(void*) this] = i;
170  }
171  // nrn_assert (gi_table.count(gi) == 0);
172  if (gi_table->count(gi) == 0) {
173  ps = new PreSyn(NULL, NULL, NULL);
175  (*gi_table)[gi] = ps;
176  ps->gid_ = -2;
177  ps->output_index_ = -2;
178  } else {
179  ps = (*gi_table)[gi];
180  }
181  NetCon* nc = new NetCon(ps, target);
183  nc->obj_ = o;
184  PyObject* po = nrnpy_ho2po(o);
185  // printf("index2target %d %s\n", gi, hoc_object_name(target));
186  return po;
187 }
188 
189 void nrnmusic_init(int* pargc, char*** pargv) {
190  int i;
191  int& argc = *pargc;
192  char**& argv = *pargv;
193  if (strlen(argv[0]) >= 5 && strcmp(argv[0] + strlen(argv[0]) - 5, "music") == 0) {
194  nrnmusic = 1;
195  }
196  for (i = 0; i < argc; ++i) {
197  if (strcmp(argv[i], "-music") == 0) {
198  nrnmusic = 1;
199  }
200  }
201  if (getenv("_MUSIC_CONFIG_"))
202  nrnmusic = 1; // temporary kludge
203  if (nrnmusic) {
204  nrnmusic_setup = new MUSIC::Setup(argc, argv);
205  nrnmusic_comm = nrnmusic_setup->communicator();
206  }
207 }
208 
210  if (!nrnmusic_runtime) {
211  nrnmusic_runtime = new MUSIC::Runtime(nrnmusic_setup, 1);
212  }
213  nrnmusic_runtime->finalize();
214  delete nrnmusic_runtime;
215 }
216 
217 // Called from nrn_spike_exchange_init so usable_mindelay is ready to use
218 // For now, can only be called once.
219 static void nrnmusic_runtime_phase() {
220  static int called = 0;
221  assert(!called);
222  called = 1;
223 
224  // call map on all the input ports
225  for (const auto& iter: *music_input_ports) {
228  Gi2PreSynTable* pst = eip->gi_table;
229  std::vector<MUSIC::GlobalIndex> gindices;
230  // iterate over pst and create indices
231  int cnt = 0;
232  for (const auto& j: *pst) {
233  int gi = j.first;
234  // printf("input port eip=%p gi=%d\n", eip, gi);
235  gindices.push_back(gi);
236  ++cnt;
237  }
238  eh->filltable(eip, cnt);
239  MUSIC::PermutationIndex indices(&gindices.front(), gindices.size());
240  eip->map(&indices, eh, usable_mindelay_ / 1000.0);
241  delete eip->gi_table;
242  }
243  delete music_input_ports;
244 
245  // call map on all the output ports
246  for (const auto& i: *music_output_ports) {
248  Gi2PreSynTable* pst = eop->gi_table;
249  std::vector<MUSIC::GlobalIndex> gindices;
250  // iterate over pst and create indices
251  for (const auto& j: *pst) {
252  int gi = j.first;
253  // printf("output port eop=%p gi = %d\n", eop, gi);
254  gindices.push_back(gi);
255  }
256  MUSIC::PermutationIndex indices(&gindices.front(), gindices.size());
257  eop->map(&indices, MUSIC::Index::GLOBAL);
258  delete eop->gi_table;
259  }
260  delete music_output_ports;
261 
262  // switch to the runtime phase
263  // printf("usable_mindelay = %g\n", usable_mindelay_);
264  nrnmusic_runtime = new MUSIC::Runtime(nrnmusic_setup, usable_mindelay_ / 1000.0);
265  npme = new NetParMusicEvent();
267 }
MusicPortPair * next_
Definition: nrnmusic.cpp:36
MusicPortPair(void *port, int gindex, void *p)
Definition: nrnmusic.cpp:38
void * port_
Definition: nrnmusic.cpp:34
void clear()
Definition: nrnmusic.cpp:48
virtual ~MusicPortPair()
Definition: nrnmusic.cpp:43
EventInputPort(MUSIC::Setup *s, std::string id)
Definition: nrnmusic.cpp:149
PyObject * index2target(int gi, PyObject *target)
Definition: nrnmusic.cpp:159
Gi2PreSynTable * gi_table
Definition: nrnmusic.h:38
void gid2index(int gid, int gi)
Definition: nrnmusic.cpp:125
Gi2PreSynTable * gi_table
Definition: nrnmusic.h:28
Definition: netcon.h:83
Object * obj_
Definition: netcon.h:113
void psl_append(PreSyn *)
Definition: netcvode.cpp:4756
TQItem * event(double tdeliver, DiscreteEvent *, NrnThread *)
Definition: netcvode.cpp:2712
virtual ~NetParMusicEvent()
Definition: nrnmusic.cpp:74
virtual void deliver(double, NetCvode *, NrnThread *)
Definition: nrnmusic.cpp:78
virtual void send(double, NetCvode *, NrnThread *)
Definition: nrnmusic.cpp:75
virtual int type()
Definition: nrnmusic.cpp:63
void filltable(NRNMUSIC::EventInputPort *, int)
Definition: nrnmusic.cpp:105
void operator()(double t, MUSIC::LocalIndex id)
Definition: nrnmusic.cpp:115
Definition: netcon.h:255
int output_index_
Definition: netcon.h:306
virtual void send(double sendtime, NetCvode *, NrnThread *)
Definition: netcvode.cpp:3252
int gid_
Definition: netcon.h:307
double t
Definition: cvodeobj.cpp:59
NetCvode * net_cvode_instance
Definition: cvodestb.cpp:27
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
#define assert(ex)
Definition: hocassrt.h:32
static int argc
Definition: inithoc.cpp:53
static char ** argv
Definition: inithoc.cpp:54
char * getenv(const char *s)
Definition: macprt.cpp:67
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
NrnThread * nrn_threads
Definition: multicore.cpp:47
EventInputPort * publishEventInput(std::string identifier)
Definition: nrnmusic.cpp:155
EventOutputPort * publishEventOutput(std::string identifier)
Definition: nrnmusic.cpp:121
static Gid2PreSyn gid2out_
Definition: netpar.cpp:33
static Symbol * netcon_sym_
Definition: netpar.cpp:32
static double usable_mindelay_
Definition: netpar.cpp:206
int is_point_process(Object *)
Definition: point.cpp:396
#define nrn_assert(ex)
Definition: nrnassrt.h:53
for(i=0;i< n;i++)
size_t p
size_t j
Object * nrnpy_po2ho(PyObject *)
Definition: nrnpy_hoc.cpp:520
MUSIC::Setup * nrnmusic_setup
Definition: nrnmusic.cpp:19
void nrnmusic_init(int *, char ***)
Definition: nrnmusic.cpp:189
void nrnmusic_terminate()
Definition: nrnmusic.cpp:209
MUSIC::Runtime * nrnmusic_runtime
Definition: nrnmusic.cpp:20
Object * hoc_new_object(Symbol *, void *)
Definition: hoc_oop.cpp:457
PyObject * nrnpy_ho2po(Object *)
Definition: nrnpy_hoc.cpp:499
void nrnmusic_spikehandle(void *vport, double tt, int gindex)
void alloc_music_space()
Definition: nrnmusic.cpp:83
void nrnmusic_injectlist(void *vp, double tt)
Definition: nrnmusic.cpp:91
int nrnmusic
MPI_Comm nrnmusic_comm
std::unordered_map< void *, int > PortTable
Definition: nrnmusic.cpp:69
static PortTable * music_output_ports
Definition: nrnmusic.cpp:71
static PortTable * music_input_ports
Definition: nrnmusic.cpp:70
static NetParMusicEvent * npme
Definition: nrnmusic.cpp:67
static void nrnmusic_runtime_phase()
Definition: nrnmusic.cpp:219
void nrnmusic_inject(void *port, int gindex, double tt)
Definition: nrnmusic.cpp:98
std::unordered_map< int, PreSyn * > Gi2PreSynTable
Definition: nrnmusic.h:13
o
Definition: seclist.cpp:175
#define cnt
Definition: spt2queue.cpp:19
#define NULL
Definition: sptree.h:16
Represent main neuron object computed by single thread.
Definition: multicore.h:58
Definition: hocdec.h:227
Definition: model.h:57
Definition: units.cpp:100