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