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