NEST  2.6.0,not_revisioned_source_dir@0
connector_model_impl.h
Go to the documentation of this file.
1 /*
2  * connector_model_impl.h
3  *
4  * This file is part of NEST.
5  *
6  * Copyright (C) 2004 The NEST Initiative
7  *
8  * NEST is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * NEST is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef CONNECTOR_MODEL_IMPL_H
24 #define CONNECTOR_MODEL_IMPL_H
25 
26 #include "nest_time.h"
27 #include "nest_timeconverter.h"
28 #include "dictutils.h"
29 #include "network.h"
30 #include "connector_model.h"
31 #include "connector_base.h"
32 
33 
34 template<typename T, typename C>
35 inline
36 T* allocate(C c)
37 {
38 #ifdef USE_PMA
39 #ifdef IS_K
40  T* p = new (poormansallocpool[omp_get_thread_num()].alloc(sizeof(T))) T(c);
41 #else
42  T* p = new (poormansallocpool.alloc(sizeof(T))) T(c);
43 #endif
44 #else
45  T* p = new T(c);
46 #endif
47  return p;
48 }
49 
50 template<typename T>
51 inline
53 {
54 #ifdef USE_PMA
55 #ifdef IS_K
56  T* p = new (poormansallocpool[omp_get_thread_num()].alloc(sizeof(T))) T();
57 #else
58  T* p = new (poormansallocpool.alloc(sizeof(T))) T();
59 #endif
60 #else
61  T* p = new T();
62 #endif
63  return p;
64 }
65 
66 
67 
68 namespace nest
69 {
70 
71  // standard implementation to obtain the default delay, assuming that it
72  // is located in GenericConnectorModel::default_connection
73  // synapse types with homogeneous delays must provide a specialization
74  // that returns the default delay from CommonProperties (or from else where)
75  // template<typename ConnectionT>
76  // double_t get_default_delay(const GenericConnectorModel<ConnectionT> &cm)
77  // {
78  // //std::cout << "standard implementation of get_default_delay" << std::endl;
79  // return cm.get_default_connection().get_delay();
80  // }
81 
82  // template<typename ConnectionT>
83  // SynIdDelay & syn_id_delay(const GenericConnectorModel<ConnectionT> &cm)
84  // {
85  // return cm.get_default_connection().get_syn_id_delay();
86  // }
87 
88  template< typename ConnectionT >
90  {
91  return new GenericConnectorModel(*this, name); // calls copy construtor
92  }
93 
94  template < typename ConnectionT >
96  {
97  // calibrate the dalay of the default properties here
98  default_connection_.calibrate(tc);
99 
100  // Calibrate will be called after a change in resolution, when there are no network elements present.
101 
102  // calibrate any time objects that might reside in CommonProperties
103  cp_.calibrate(tc);
104 
105  min_delay_ = tc.from_old_steps(min_delay_.get_steps());
106  max_delay_ = tc.from_old_steps(max_delay_.get_steps());
107  }
108 
109  template < typename ConnectionT >
111  {
112  // first get properties common to all synapses
113  // these are stored only once (not within each Connection)
114  cp_.get_status(d);
115 
116  // then get default properties for individual synapses
117  default_connection_.get_status(d);
118 
119  (*d)["min_delay"] = get_min_delay().get_ms();
120  (*d)["max_delay"] = get_max_delay().get_ms();
121  (*d)[names::receptor_type] = receptor_type_;
122  (*d)["synapsemodel"] = LiteralDatum(name_);
123 
124  long_t old_count;
125  // if field "num_connections" already exists
126  // we will add to this number
127  // used to add up connections from connector_models
128  // for different threads
129  if ( updateValue<long_t>(d, "num_connections", old_count) )
130  (*d)["num_connections"] = old_count + get_num_connections();
131  else
132  (*d)["num_connections"] = get_num_connections();
133  }
134 
135  template < typename ConnectionT >
137  {
138  updateValue<long_t>(d, names::receptor_type, receptor_type_);
139 #ifdef HAVE_MUSIC
140  // We allow music_channel as alias for receptor_type during connection setup
141  updateValue<long_t>(d, names::music_channel, receptor_type_);
142 #endif
143 
144  /*
145  * In the following code, we do not round delays to steps. For min and max delay,
146  * this is not strictly necessary. For a newly set delay, the rounding will be
147  * handled in cp_.set_status() or default_connection_.set_status().
148  * Since min_/max_delay are Time-objects and comparison is defined on Time
149  * objects, we should use it.
150  */
151  Time min_delay, max_delay, new_delay;
152  double_t delay_tmp;
153  bool min_delay_updated = updateValue<double_t>(d, "min_delay", delay_tmp);
154  min_delay = Time(Time::ms(delay_tmp));
155  bool max_delay_updated = updateValue<double_t>(d, "max_delay", delay_tmp);
156  max_delay = Time(Time::ms(delay_tmp));
157 
158  // the delay might also be updated, so check new_min_delay and new_max_delay against new_delay, if given
159  if (! updateValue<double_t>(d, "delay", delay_tmp))
160  new_delay = Time(Time::ms(default_connection_.get_delay()));
161  else
162  new_delay = Time(Time::ms(delay_tmp));
163 
164  if (min_delay_updated xor max_delay_updated)
165  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
166  "Both min_delay and max_delay have to be specified");
167 
168  if (min_delay_updated && max_delay_updated)
169  {
170  if (num_connections_ > 0)
171  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
172  "Connections already exist. Please call ResetKernel first");
173  else if ( min_delay > new_delay )
174  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
175  "min_delay is not compatible with default delay");
176  else if ( max_delay < new_delay )
177  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
178  "max_delay is not compatible with default delay");
179  else if ( min_delay < Time::get_resolution() )
180  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
181  "min_delay must be greater than or equal to resolution");
182  else if ( max_delay < Time::get_resolution() )
183  net_.message(SLIInterpreter::M_ERROR, "SetDefaults",
184  "max_delay must be greater than or equal to resolution");
185  else
186  {
187  min_delay_ = min_delay;
188  max_delay_ = max_delay;
189  user_set_delay_extrema_ = true;
190  }
191  }
192 
193  // common_props_.set_status(d, *this) AND defaults_.set_status(d, *this);
194  // has to be done after adapting min_delay / max_delay, since Connection::set_status
195  // and CommonProperties::set_status might want to check the delay
196 
197  // store min_delay_, max_delay_
198  // calling set_status will check the delay.
199  // and so may modify min_delay, max_delay, if the specified delay exceeds one of these bounds
200  // we have to save min/max_delay because we dont know, if the default will ever be used
201  Time min_delay_tmp = min_delay_;
202  Time max_delay_tmp = max_delay_;
203 
204  cp_.set_status(d, *this);
205  default_connection_.set_status(d, *this);
206 
207  // restore min_delay_, max_delay_
208  min_delay_ = min_delay_tmp;
209  max_delay_ = max_delay_tmp;
210 
211  // we've possibly just got a new default delay. So enforce checking next time it is used
212  default_delay_needs_check_ = true;
213  }
214 
215  template < typename ConnectionT >
217  {
218  // if not used before, check now. Solves bug #138, MH 08-01-08
219  // replaces whole delay checking for the default delay, see bug #217, MH 08-04-24
220  // get_default_delay_ must be overridded by derived class to return the correct default delay
221  // (either from commonprops or default connection)
222  if (default_delay_needs_check_)
223  {
224  assert_valid_delay_ms(default_connection_.get_delay());
225  default_delay_needs_check_ = false;
226  }
227  }
228 
229  template < typename ConnectionT >
231  {
232  default_connection_.set_syn_id(syn_id);
233  }
234 
241  template < typename ConnectionT >
244  {
245  if (! std::isnan(delay))
246  assert_valid_delay_ms(delay);
247 
248  // create a new instance of the default connection
249  ConnectionT c = ConnectionT( default_connection_ );
250  if (! std::isnan(weight))
251  {
252  c.set_weight(weight);
253  }
254  if (! std::isnan(delay))
255  {
256  c.set_delay(delay);
257  }
258  else
259  {
260  // tell the connector model, that we used the default delay
261  used_default_delay();
262  }
263 
264 
265  return add_connection(src, tgt, conn, syn_id, c, receptor_type_);
266  }
267 
274  template< typename ConnectionT >
277  {
278  if (! std::isnan(delay))
279  {
280  assert_valid_delay_ms(delay);
281 
282  if ( p->known(names::delay) )
283  throw BadParameter("Parameter dictionary must not contain delay if delay is given explicitly.");
284  }
285  else
286  {
287  // check delay
288  double_t delay = 0.0;
289 
290  if ( updateValue<double_t>(p, names::delay, delay) )
291  assert_valid_delay_ms(delay);
292  else
293  used_default_delay();
294  }
295 
296  // create a new instance of the default connection
297  ConnectionT c = ConnectionT( default_connection_ );
298  if (!p->empty())
299  c.set_status(p, *this); // reference to connector model needed here to check delay (maybe this could be done one level above?)
300  if (! std::isnan(weight))
301  {
302  c.set_weight(weight);
303  }
304  if (! std::isnan(delay))
305  {
306  c.set_delay(delay);
307  }
308 
309  // We must use a local variable here to hold the actual value of the
310  // receptor type. We must not change the receptor_type_ data member, because
311  // that represents the *default* value. See #921.
312  rport actual_receptor_type = receptor_type_;
313 #ifdef HAVE_MUSIC
314  // We allow music_channel as alias for receptor_type during connection setup
315  updateValue<long_t>(p, names::music_channel, actual_receptor_type);
316 #endif
317  updateValue<long_t>(p, names::receptor_type, actual_receptor_type);
318 
319  return add_connection(src, tgt, conn, syn_id, c, actual_receptor_type);
320  }
321 
322 
323 
324  // needs Connection < >
325 
326  template < typename ConnectionT >
328  synindex syn_id, ConnectionT& c, rport receptor_type)
329  {
330  // here we need to distinguish several cases:
331  // - neuron src has no target on this machine yet (case 0)
332  // - neuron src has n targets on this machine, all of same type syn_id_existing (case 1)
333  // -- new connection of type syn_id == syn_id_existing
334  // -- new connection of type syn_id != syn_id_existing
335  // - neuron src has n targets of more than a single synapse type (case 2)
336  // -- there are already synapses of type syn_id
337  // -- there are no connections of type syn_id yet
338 
339  if (conn == 0)
340  {
341  // case 0
342 
343  // the following line will throw an exception, if it does not work
344  c.check_connection(src, tgt, receptor_type, 0., get_common_properties()); // set last_spike to 0
345 
346  // no entry at all, so start with homogeneous container for exactly one connection
347  conn = allocate< Connector<1, ConnectionT> >(c);
348  }
349  else
350  {
351  // case 1 or case 2
352 
353  // the following line will throw an exception, if it does not work
354  c.check_connection(src, tgt, receptor_type, conn->get_t_lastspike(), get_common_properties());
355 
356  if ( conn->homogeneous_model() ) // there is already a homogeneous entry
357  {
358  if (conn->get_syn_id() == syn_id) // case 1: connector for this syn_id
359  {
360  // we can safely static cast, because we checked syn_id == syn_id(connectionT)
361  vector_like<ConnectionT> *vc = static_cast< vector_like<ConnectionT>* > (conn);
362  conn = & vc->push_back(c);
363  }
364  else
365  {
366  // syn_id is different from the one stored in the homogeneous connector
367  // we need to create a heterogeneous connector now and insert the existing
368  // homogeneous connector and a new homogeneous connector for the new syn_id
369  HetConnector *hc = allocate<HetConnector>();
370 
371  // add existing connector
372  hc->push_back( conn );
373 
374  // create hom connector for new synid
375  vector_like<ConnectionT> * vc = allocate<Connector<1, ConnectionT> >(c);
376 
377  // append new homogeneous connector to heterogeneous connector
378  hc->push_back( vc );
379 
380  // make entry in connections_[sgid] point to new heterogeneous connector
381  conn = hc;
382  }
383  }
384  else // case 2: the entry is heterogeneous, need to search for syn_id
385  {
386  // go through all entries and search for correct syn_id
387  // if not found create new entry for this syn_id
388  HetConnector *hc = static_cast< HetConnector* >(conn);
389  bool found = false;
390  for (size_t i=0; i<hc->size() && !found; i++)
391  {
392  // need to cast to vector_like to access syn_id
393  if ((*hc)[i]->get_syn_id() == syn_id) // there is already an entry for this type
394  {
395  // here we know that the type is vector_like<connectionT>, because syn_id agrees
396  // so we can savely static cast
397  vector_like<ConnectionT>* vc = static_cast< vector_like<ConnectionT>* > ( (*hc)[i] );
398  (*hc)[i] = & vc->push_back(c);
399  found = true;
400  }
401  } // of for
402  if (!found) // we need to create a new entry for this type of connection
403  {
404  vector_like<ConnectionT> * vc = allocate<Connector<1, ConnectionT> >(c);
405 
406  hc->push_back(vc);
407  }
408  }
409  }
410 
411  num_connections_++;
412 
413  return conn;
414  }
415 
416 
417 
418 
419 
420 
422 // Convenient versions of template functions for registering new synapse types //
423 // by modules //
425 
429  template <class ConnectionT>
430  synindex register_connection_model (Network& net, const std::string &name)
431  {
433  }
434 
435 } // namespace nest
436 
437 #endif
double_t weight
Weight of a connection.
Definition: nest.h:170
const Name delay("delay")
Connection parameters.
Definition: nest_names.h:92
const Name receptor_type("receptor_type")
Connection parameters.
Definition: nest_names.h:240
const Name music_channel("music_channel")
Parameters for MUSIC devices.
Definition: nest_names.h:200
const Name d("d")
Specific to Izhikevich 2003.
Definition: nest_names.h:83
void set_status(const DictionaryDatum &)
Definition: connector_model_impl.h:136
synindex register_synapse_prototype(ConnectorModel *cf)
Register a synapse prototype at the connection manager.
Definition: network.h:942
Definition: connector_base.h:88
double_t get_t_lastspike() const
Definition: connector_base.h:119
Time from_old_steps(long_t s_old) const
Converts a given number of steps with respect to old representation into a time object in current rep...
Definition: nest_timeconverter.cpp:34
ConnectorModel * clone(std::string) const
Definition: connector_model_impl.h:89
long_t rport
Connection port number to distinguish incoming connections, also called receiver port.
Definition: nest.h:147
Definition: nest_time.h:235
Exception to be thrown if a parameter cannot be set.
Definition: exceptions.h:445
Definition: nest_time.h:130
T * allocate(C c)
Definition: connector_model_impl.h:36
void set_syn_id(synindex syn_id)
Definition: connector_model_impl.h:230
Definition: connector_base.h:445
Declarations for class Network.
Main administrative interface to the network.
Definition: network.h:135
Class to convert times from one representation to another.
Definition: nest_timeconverter.h:45
void used_default_delay()
Definition: connector_model_impl.h:216
void * alloc(size_t obj_size)
Definition: allocator.cpp:174
double double_t
Double precision floating point numbers.
Definition: nest.h:93
Definition: namedatum.h:90
static Time get_resolution()
Definition: nest_time.h:303
unsigned char synindex
Unsigned char type for enumerations of synapse types.
Definition: nest.h:115
void get_status(DictionaryDatum &) const
Definition: connector_model_impl.h:110
long_t delay
Delay of a connection.
Definition: nest.h:178
virtual ConnectorBase & push_back(const ConnectionT &c)=0
Base class for all NEST network objects.
Definition: node.h:96
static const int M_ERROR
Predefined error level for error messages.
Definition: interpret.h:180
void calibrate(const TimeConverter &tc)
Definition: connector_model_impl.h:95
virtual bool homogeneous_model()=0
const Name p("p")
current release probability (Tsodyks2_connection)
Definition: nest_names.h:218
const Name c("c")
Specific to Izhikevich 2003.
Definition: nest_names.h:62
Definition: connector_model.h:38
long long_t
Integer number with at least 32 bit.
Definition: nest.h:96
Definition: connector_base.h:132
Definition: connector_model.h:113
PoorMansAllocator poormansallocpool
Definition: allocator.cpp:196
ConnectorBase * add_connection(Node &src, Node &tgt, ConnectorBase *conn, synindex syn_id, double_t weight, double_t delay)
delay and weight have the default value NAN.
Definition: connector_model_impl.h:242
virtual synindex get_syn_id() const =0
synindex register_connection_model(Network &net, const std::string &name)
Register a synape with default Connector and without any common properties.
Definition: connector_model_impl.h:430