1 /*
2 * model_manager.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 MODEL_MANAGER_H
24 #define MODEL_MANAGER_H
25
26 // C++ includes:
27 #include <string>
28
29 // Includes from nestkernel:
30 #include "connector_model.h"
31 #include "genericmodel.h"
32 #include "manager_interface.h"
33 #include "model.h"
34 #include "nest.h"
35 #include "nest_time.h"
36 #include "nest_timeconverter.h"
37 #include "nest_types.h"
38 #include "node.h"
39
40 // Includes from sli:
41 #include "dictutils.h"
42
43 namespace nest
44 {
45 class ModelManager : public ManagerInterface
46 {
47 public:
48 ModelManager();
49 ~ModelManager();
50
51 /**
52 *
53 */
54 virtual void initialize();
55
56 /**
57 *
58 */
59 virtual void finalize();
60
61 /**
62 * Resize the structures for the Connector objects if necessary.
63 * This function should be called after number of threads, min_delay,
64 * max_delay, and time representation have been changed in the scheduler.
65 * The TimeConverter is used to convert times from the old to the new
66 * representation. It is also forwarding the calibration
67 * request to all ConnectorModel objects.
68 */
69 void calibrate( const TimeConverter& );
70
71 /**
72 *
73 */
74 virtual void set_status( const DictionaryDatum& );
75
76 /**
77 *
78 */
79 virtual void get_status( DictionaryDatum& );
80
81 /**
82 *
83 */
84 Node* get_proxy_node( thread tid, index node_id );
85
86 /**
87 *
88 */
89 Node* get_dummy_spike_source( thread );
90
91 /**
92 * Return pointer to protoype for given synapse id.
93 * @throws UnknownSynapseType
94 */
95
96 // TODO: make the return type const, after the increment of
97 // num_connections and the min_ and max_delay setting in
98 // ConnectorBase was moved out to the ConnectionManager
99 ConnectorModel& get_synapse_prototype( synindex syn_id, thread t = 0 );
100
101 const std::vector< ConnectorModel* >& get_synapse_prototypes( thread tid );
102
103 /**
104 * Register a node-model prototype.
105 * This function must be called exactly once for each model class to make
106 * it known in the simulator. The natural place for a call to this function
107 * is in a *module.cpp file.
108 * @param name of the new node model.
109 * @param private_model if true, don't add model to modeldict.
110 * @param deprecation_info If non-empty string, deprecation warning will
111 * be issued for model with this info to user.
112 * @return ID of the new model object.
113 * @see register_private_prototype_model, register_preconf_node_model,
114 * register_prototype_connection
115 */
116 template < class ModelT >
117 index
118 register_node_model( const Name& name, bool private_model = false, std::string deprecation_info = std::string() );
119
120 /**
121 * Register a pre-configured model prototype with the network.
122 * This function must be called exactly once for each model class to make
123 * it known to the network. The natural place for a call to this function
124 * is in a *module.cpp file.
125 *
126 * Pre-configured models are models based on the same class, as
127 * another model, but have different parameter settings; e.g.,
128 * voltmeter is a pre-configured multimeter.
129 *
130 * @param name of the new node model.
131 * @param private_model if true, don't add model to modeldict.
132 * @param dictionary to use to pre-configure model
133 * @param deprecation_info If non-empty string, deprecation warning will
134 * be issued for model with this info to user.
135 *
136 * @return ID of the new model object.
137 * @see register_private_prototype_model, register_node_model,
138 * register_prototype_connection
139 */
140 template < class ModelT >
141 index register_preconf_node_model( const Name& name,
142 DictionaryDatum& conf,
143 bool private_model = false,
144 std::string deprecation_info = std::string() );
145
146 /**
147 * Copy an existing model and register it as a new model.
148 * This function allows users to create their own, cloned models.
149 * @param old_name name of existing model.
150 * @param new_name name of new model.
151 * @param params default parameters of new model.
152 * @return model ID of new Model object.
153 * @see copy_node_model_, copy_synapse_model_
154 */
155 index copy_model( Name old_name, Name new_name, DictionaryDatum params );
156
157 /**
158 * Set the default parameters of a model.
159 * @param name of model.
160 * @param params default parameters to be set.
161 * @see set_node_defaults_, set_synapse_defaults_
162 */
163 void set_model_defaults( Name name, DictionaryDatum params );
164
165 /**
166 * Register a synape model with a custom Connector model and without any
167 * common properties.
168 *
169 * "hpc synapses" use `TargetIdentifierIndex` for `ConnectionT` and store
170 * the target neuron in form of a 2 Byte index instead of an 8 Byte pointer.
171 * This limits the number of thread local neurons to 65,536. No support for
172 * different receptor types. Otherwise identical to non-hpc version.
173 *
174 * When called, this function should be specialised by a class template,
175 * e.g. `bernoulli_synapse< targetidentifierT >`
176 *
177 * @param name The name under which the ConnectorModel will be registered.
178 */
179 template < template < typename targetidentifierT > class ConnectionT >
180 void register_connection_model( const std::string& name,
181 const RegisterConnectionModelFlags flags = default_connection_model_flags );
182
183 template < template < typename targetidentifierT > class ConnectionT >
184 void register_secondary_connection_model( const std::string& name,
185 const RegisterConnectionModelFlags flags = default_secondary_connection_model_flags );
186
187 /**
188 * @return The model id of a given model name
189 */
190 int get_model_id( const Name ) const;
191
192 /**
193 * @return The Model of a given model ID
194 */
195 Model* get_model( index ) const;
196
197 DictionaryDatum get_connector_defaults( synindex syn_id ) const;
198
199 /**
200 * Checks, whether synapse type requires symmetric connections
201 */
202 bool connector_requires_symmetric( const synindex syn_id ) const;
203
204 /**
205 * Checks, whether synapse type requires Clopath archiving
206 */
207 bool connector_requires_clopath_archiving( const synindex syn_id ) const;
208
209 /**
210 * Checks, whether synapse type requires Urbanczik archiving
211 */
212 bool connector_requires_urbanczik_archiving( const synindex syn_id ) const;
213
214 void set_connector_defaults( synindex syn_id, const DictionaryDatum& d );
215
216 /**
217 * Check, if there are instances of a given model.
218 * @param i the index of the model to check for.
219 * @return True, if model is instantiated at least once.
220 */
221 bool is_model_in_use( index i );
222
223 /**
224 * Checks, whether connections of the given type were created
225 */
226 bool synapse_prototype_in_use( synindex syn_id );
227
228 /**
229 * Asserts validity of synapse index, otherwise throws exception.
230 * @throws UnknownSynapseType
231 */
232 void assert_valid_syn_id( synindex syn_id, thread t = 0 ) const;
233
234 /**
235 * @return Reference to the model dictionary
236 */
237 DictionaryDatum& get_modeldict();
238
239 /**
240 * @return Reference to the synapse dictionary
241 */
242 DictionaryDatum& get_synapsedict();
243
244 /**
245 * Does the network contain copies of models created using CopyModel?
246 */
247 bool has_user_models() const;
248
249 bool has_user_prototypes() const;
250
251 bool are_model_defaults_modified() const;
252
253 const std::vector< ConnectorModel* >& get_prototypes( const thread t ) const;
254
255 size_t get_num_node_models() const;
256
257 size_t get_num_synapse_prototypes() const;
258
259 /**
260 * Print out the memory information for each node model.
261 * @see sli::pool
262 */
263 void memory_info() const;
264
265 void create_secondary_events_prototypes();
266
267 void delete_secondary_events_prototypes();
268
269 SecondaryEvent& get_secondary_event_prototype( const synindex syn_id, const thread tid ) const;
270
271 private:
272 /** */
273 void clear_models_();
274
275 /** */
276 void clear_prototypes_();
277
278 /** */
279 index register_node_model_( Model* model, bool private_model = false );
280
281 synindex register_connection_model_( ConnectorModel* );
282
283 /**
284 * Copy an existing node model and register it as a new model.
285 * @param old_id ID of existing model.
286 * @param new_name name of new model.
287 * @return model ID of new Model object.
288 * @see copy_model(), copy_synapse_model_()
289 */
290 index copy_node_model_( index old_id, Name new_name );
291
292 /**
293 * Copy an existing synapse model and register it as a new model.
294 * @param old_id ID of existing model.
295 * @param new_name name of new model.
296 * @return model ID of new Model object.
297 * @see copy_model(), copy_node_model_()
298 */
299 index copy_synapse_model_( index old_id, Name new_name );
300
301 /**
302 * Set the default parameters of a model.
303 * @param model_id of model.
304 * @param params default parameters to be set.
305 * @see set_model_defaults, set_synapse_defaults_
306 */
307 void set_node_defaults_( index model_id, const DictionaryDatum& params );
308
309 /**
310 * Set the default parameters of a model.
311 * @param name of model.
312 * @param params default parameters to be set.
313 * @see set_model_defaults, set_node_defaults_
314 */
315 void set_synapse_defaults_( index model_id, const DictionaryDatum& params );
316
317 //! Compares model ids for sorting in memory_info
318 static bool compare_model_by_id_( const int a, const int b );
319
320 /**
321 * The list of clean node models. The first component of the pair is a
322 * pointer to the actual Model, the second is a flag indicating if
323 * the model is private. Private models are not entered into the
324 * modeldict.
325 */
326 std::vector< std::pair< Model*, bool > > pristine_models_;
327
328 std::vector< Model* > models_; //!< List of available models
329
330
331 /**
332 * The list of clean synapse models. The first component of the pair is a
333 * pointer to the actual Model, the second is a flag indicating if
334 * the model is private. Private models are not entered into the
335 * modeldict.
336 */
337 std::vector< ConnectorModel* > pristine_prototypes_;
338
339 /**
340 * The list of available synapse prototypes: first dimension one
341 * entry per thread, second dimension for each synapse type
342 */
343 std::vector< std::vector< ConnectorModel* > > prototypes_;
344
345 std::vector< ConnectorModel* > secondary_connector_models_;
346 std::vector< std::map< synindex, SecondaryEvent* > > secondary_events_prototypes_;
347
348 /** @BeginDocumentation
349 Name: modeldict - dictionary containing all devices and models of NEST
350
351 Description:
352 'modeldict info' shows the contents of the dictionary
353
354 SeeAlso: info, Device, RecordingDevice
355 */
356 DictionaryDatum modeldict_; //!< Dictionary of all models
357
358 /** @BeginDocumentation
359 Name: synapsedict - Dictionary containing all synapse models.
360
361 Description:
362 'synapsedict info' shows the contents of the dictionary
363 Synapse model names ending with '_hpc' provide minimal memory requirements by
364 using thread-local target neuron IDs and fixing the `rport` to 0.
365 Synapse model names ending with '_lbl' allow to assign an individual integer
366 label (`synapse_label`) to created synapses at the cost of increased memory
367 requirements.
368
369 FirstVersion: October 2005
370
371 Author: Jochen Martin Eppler
372
373 SeeAlso: info
374 */
375 DictionaryDatum synapsedict_; //!< Dictionary of all synapse models
376
377 Model* proxynode_model_;
378
379 Node* create_proxynode_( thread t, int model_id );
380
381 //! Placeholders for remote nodes, one per thread
382 std::vector< std::vector< Node* > > proxy_nodes_;
383 //! Placeholders for spiking remote nodes, one per thread
384 std::vector< Node* > dummy_spike_sources_;
385 //! True if any model defaults have been modified
386 bool model_defaults_modified_;
387 };
388
389
390 inline Model*
get_model(index m)391 ModelManager::get_model( index m ) const
392 {
393 if ( m >= models_.size() or models_[ m ] == 0 )
394 {
395 throw UnknownModelID( m );
396 }
397
398 return models_[ m ];
399 }
400
401 inline Node*
get_dummy_spike_source(thread tid)402 ModelManager::get_dummy_spike_source( thread tid )
403 {
404 return dummy_spike_sources_[ tid ];
405 }
406
407 inline bool
are_model_defaults_modified()408 ModelManager::are_model_defaults_modified() const
409 {
410 return model_defaults_modified_;
411 }
412
413 inline DictionaryDatum&
get_modeldict()414 ModelManager::get_modeldict()
415 {
416 return modeldict_;
417 }
418
419 inline DictionaryDatum&
get_synapsedict()420 ModelManager::get_synapsedict()
421 {
422 return synapsedict_;
423 }
424
425 inline bool
has_user_models()426 ModelManager::has_user_models() const
427 {
428 return models_.size() > pristine_models_.size();
429 }
430
431 inline ConnectorModel&
get_synapse_prototype(synindex syn_id,thread t)432 ModelManager::get_synapse_prototype( synindex syn_id, thread t )
433 {
434 assert_valid_syn_id( syn_id );
435 return *( prototypes_[ t ][ syn_id ] );
436 }
437
438 inline const std::vector< ConnectorModel* >&
get_synapse_prototypes(thread tid)439 ModelManager::get_synapse_prototypes( thread tid )
440 {
441 return prototypes_[ tid ];
442 }
443
444 inline size_t
get_num_node_models()445 ModelManager::get_num_node_models() const
446 {
447 return models_.size();
448 }
449
450 inline size_t
get_num_synapse_prototypes()451 ModelManager::get_num_synapse_prototypes() const
452 {
453 assert( prototypes_[ 0 ].size() <= invalid_synindex );
454 return prototypes_[ 0 ].size();
455 }
456
457 inline void
assert_valid_syn_id(synindex syn_id,thread t)458 ModelManager::assert_valid_syn_id( synindex syn_id, thread t ) const
459 {
460 if ( syn_id >= prototypes_[ t ].size() or prototypes_[ t ][ syn_id ] == 0 )
461 {
462 throw UnknownSynapseType( syn_id );
463 }
464 }
465
466 inline bool
has_user_prototypes()467 ModelManager::has_user_prototypes() const
468 {
469 return prototypes_[ 0 ].size() > pristine_prototypes_.size();
470 }
471
472 inline void
delete_secondary_events_prototypes()473 ModelManager::delete_secondary_events_prototypes()
474 {
475 for ( std::vector< std::map< synindex, SecondaryEvent* > >::iterator it = secondary_events_prototypes_.begin();
476 it != secondary_events_prototypes_.end();
477 ++it )
478 {
479 for ( std::map< synindex, SecondaryEvent* >::iterator iit = it->begin(); iit != it->end(); ++iit )
480 {
481 ( *iit->second ).reset_supported_syn_ids();
482 delete iit->second;
483 }
484 }
485 secondary_events_prototypes_.clear();
486 }
487
488 inline SecondaryEvent&
get_secondary_event_prototype(const synindex syn_id,const thread tid)489 ModelManager::get_secondary_event_prototype( const synindex syn_id, const thread tid ) const
490 {
491 assert_valid_syn_id( syn_id );
492 // Using .at() because operator[] does not guarantee constness.
493 return *( secondary_events_prototypes_[ tid ].at( syn_id ) );
494 }
495
496 } // namespace nest
497
498 #endif /* MODEL_MANAGER_H */
499