diff --git a/doc/htmldoc/developer_space/axonal_delays.rst b/doc/htmldoc/developer_space/axonal_delays.rst new file mode 100644 index 0000000000..5e3c405a56 --- /dev/null +++ b/doc/htmldoc/developer_space/axonal_delays.rst @@ -0,0 +1,86 @@ +.. _axonal_delays_dev: + +Axonal Delays +============= + +Adding axonal delays to NEST is non-trivial when it comes to their interaction with spike-timing dependent plasticity (STDP). +Axonal delays lower than their dendritic counterpart are non-problematic, however larger axonal delays cause causality +issues due to the way how and when pre- and post-synaptic spikes are processed in NEST by synapses implementing STDP weight dynamics. + +If a pre-synaptic spike is processed at a synapse, it will also process all post-synaptic spikes that reached the synapse +between the last and current pre-synaptic spike. Weight changes due facilitation (post-synaptic spike following a +pre-synaptic one) or depression (pre-synaptic spike following a post-synaptic one) are only relevant at the time when pre-synaptic spikes +reach the synapse, as this is the only point in time when the exact weight is of importance. Post-synaptic spikes can +therefore be archived in the post-synaptic neuron until the next pre-synaptic spike is processed by the synapse. +As all pre-synaptic spikes are delivered to their target synapse and neuron right after they have been communicated, +they might be processed before they would actually reach the synapse when taking axonal delays into account. +If the axonal delay is now larger than the dendritic delay, post-synaptic +spikes occurring at time `t` will reach the synapse before pre-synaptic spikes occurring before `t`, +but might not be taken into account by the pre-synaptic spike, if it was already communicated, +and thus delivered, before `t`. Each pre-synaptic spike sent over a connection +with a predominant axonal delay must therefore also process post-synaptic spikes which have not yet occurred, +but could be emitted in the future. Multiple implementations were implemented and +benchmarked before coming to the conclusion that the implementation at hand should be used inside NEST. + +The main idea of the axonal delays implementation in NEST is based on the fact, that neurons only emit few spikes per second. +It should thus be rare that a post-synaptic spike occurs right after a pre-synaptic one in the critical region before +the pre-synaptic spike reaches the synapse, but has already been processed. In typical networks, there will most likely +only be few occurrences where causality becomes an issue. In order to still guarantee correct synaptic weights, +incorrect STDP weight changes are rolled back, re-calculated, and the weight of pre-synaptic spike, which already reached +the target neuron's ring buffer, is corrected. Undoing the STDP weight changes and re-calculating them obviously comes +with a cost, however as only few such occurrences are to be expected, this solution is more efficient than restructuring +the kernel to make sure axonal delays are always handled correctly (see Alternative implementations). + +Changes to the kernel and neuron models +--------------------------------------- + +Introducing axonal delays changes the way the min- and max-delays must be calculated, as they are now a combination of +dendritic and axonal delays. The default value for the delay which is now referring to the dendritic delay remains 1, +while the default value for axonal_delay is set to 0. In the default case, purely dendritic delay is assumed. + +The ``ArchivingNode`` was made axonal-delay-aware. Each pre-synaptic spike after which a correction could potentially follow, +will be archived in the post-synaptic neuron in a dynamic ring-buffer-like structure. Post-synaptic spikes will then +trigger a correction for all relevant pre-synaptic spikes in this buffer. The way spikes are received at a neuron is +model-dependent, as the implementation of spike accumulation and buffering until being processed might vary between +neuron models. Neurons models will therefore also have to handle correction of previously handled spikes differently. +In the simplest case, all incoming spikes to a neuron are simply accumulated in a single scalar value per time slot. +A correction of a previously handled spike would therefore just subtract the previous, wrong weight and add the new, +corrected weight. Therefore, simply sending another spike with the difference of the old and new weight would be +sufficient in this case. However, some neurons might have different buffers for spikes being sent over inhibitory and +excitatory connections, which could be distinguished by the sign of the weight. If a new spike is now sent to correct +an old one, the sign might be negative even though both the old and new weight were originally positive, the new weight +is just smaller. In such a case, the spike would be accumulated in the wrong buffer. + +Instead of sending a regular ``SpikeEvent`` to signal a correction, a ``CorrectionSpikeEvent`` is sent. Overloading the handle +function now allows handling the correction in the correct way, depending on the model implementation. +Furthermore, neuron models must now call ``ArchivingNode::pre_run_hook_()`` in their derived pre_run_hook implementation +and call ``reset_correction_entries_stdp_ax_delay_()`` at the end of their update implementation. +Currently, only the ``iaf_psc_alpha`` neuron model supports STDP with axonal delays. +All other neurons will act as if the delay of incoming connections was purely dendritic. + +Synapse models only support dendritic delay by default. If axonal delays are required, the synapse model must be derived +from ``AxonalDelayConnection`` instead of ``Connection``. The ``AxonalDelayConnection`` is derived from ``Connection`` and adds a single +double-precision member for the axonal delay. The main differences compared to synapses with purely dendritic delays are +different handling of delays inside the send function and the addition of the ``correct_synapse_stdp_ax_delay`` which is +called by the ``ConnectionManager`` when a synapse needs to re-calculate its weight given a new post-synaptic spike and a previous pre-synaptic one. +Currently, only the ``stdp_pl_synapse_hom_ax_delay`` synapse model supports axonal delays. + +Changes to the python interface +------------------------------- + +In general, the kernel was made axonal-delay-aware and this is reflected in the user interface, as it is now possible +to set the ``names::dendritic_delay`` and ``names::axonal_delay`` for each synapse (given that the synapse model is +derived from ``AxonalDelayConnection``). + +Remaining work +--------------- + + +Currently, only one neuron and synapse model are supporting axonal delays. All neuron models that support STDP could +also support axonal delays, without sacrificing performance, changing their behavior, or requiring more memory, but need +to be adapted slightly (i.e., implement handle for ``CorrectionSpikeEvent``, call ``ArchivingNode::pre_run_hook_`` and call +``reset_correction_entries_stdp_ax_delay_``). + +Existing STDP synapse models need one version with and one without axonal delays. Alternatively, synapse models could +be templatized to either use only dendritic or dendritic and axonal delays. However, this branching should be resolved +at compile time to not negatively impact performance. diff --git a/doc/htmldoc/developer_space/index.rst b/doc/htmldoc/developer_space/index.rst index f0b8125e4f..16b4ecd570 100644 --- a/doc/htmldoc/developer_space/index.rst +++ b/doc/htmldoc/developer_space/index.rst @@ -122,4 +122,5 @@ Developer guides guidelines/styleguide/vim_support_sli templates/* sli_docs/index + axonal_delays cppcomments diff --git a/doc/htmldoc/examples/index.rst b/doc/htmldoc/examples/index.rst index cbd061272b..287d7d4e00 100644 --- a/doc/htmldoc/examples/index.rst +++ b/doc/htmldoc/examples/index.rst @@ -219,6 +219,10 @@ PyNEST examples * :doc:`/auto_examples/eprop_plasticity/eprop_supervised_regression_sine-waves` * :doc:`/auto_examples/eprop_plasticity/eprop_supervised_classification_neuromorphic_mnist` + .. grid-item-card:: Axonal delays + :img-top: ../static/img/nest_logo-faded.png + + * :doc:`/auto_examples/axonal_delays` .. grid:: 1 1 2 3 @@ -340,4 +344,4 @@ PyNEST examples ../auto_examples/astrocytes/index ../auto_examples/EI_clustered_network/index ../auto_examples/eprop_plasticity/index - ../auto_examples/wang_decision_making + ../auto_examples/wang_decision_making \ No newline at end of file diff --git a/doc/htmldoc/get-started_index.rst b/doc/htmldoc/get-started_index.rst index 0e8ff5eb17..c84897eb83 100644 --- a/doc/htmldoc/get-started_index.rst +++ b/doc/htmldoc/get-started_index.rst @@ -159,6 +159,7 @@ More topics * :ref:`sim_gap_junctions` * :ref:`weight_normalization` + * :ref:`delays` diff --git a/doc/htmldoc/synapses/delays.rst b/doc/htmldoc/synapses/delays.rst new file mode 100644 index 0000000000..d8dab296d6 --- /dev/null +++ b/doc/htmldoc/synapses/delays.rst @@ -0,0 +1,73 @@ +.. _delays: + +Delays +====== + + +In NEST, transmission delays are specified with the ``delay`` parameter. +Delays are considered fully dendritic by all built-in models and therefore, the ``delay`` parameter is still used by +most models. + +Since NEST 3.9, it is also possible to specify both explicit, heterogeneous axonal and dendritic delays for models +supporting this feature. This is useful for STDP models and other models relying on the timing of spike arrival at the +synapse. + +Currently, only ``stdp_pl_synapse_hom_ax_delay`` supports explicitly specifying axonal and dendritic delays with the +``axonal_delay`` and ``dendtritic_delay`` parameters. For STDP with predominant axonal delays, neuron models must be +adjusted to correctly handle these delays. At this point, only ``iaf_psc_alpha`` supports STDP with predominant axonal +delays. + +When using ``stdp_pl_synapse_hom_ax_delay``: + +- The parameter ``delay`` is no longer valid. This is to prevent ambiguity between the two types of delays. +- The parameter names ``dendritic_delay`` and ``axonal_delay`` have to be used to specify delay. +- If these parameters are not explicitly provided, then the default values are used: + + ``dendritic_delay: 1.0`` and ``axonal_delay: 0.0``. +- If only axonal delay is provided and no dendritic delay, the dendritic delay is assumed to be 0 and vice-versa. + + +Use of ``axonal_delay`` and ``dendritic_delay`` is the same as ``delay``: + + +**Using syn_spec** + +.. code-block:: python + + nest.Create("iaf_psc_alpha") + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom", "delay": 1.0}) + +.. code-block:: python + + nest.Create("iaf_psc_alpha") + nest.Connect(neuron, neuron, syn_spec= + {"synapse_model": "stdp_pl_synapse_hom_ax_delay", "axonal_delay": 1.0, "dendritic_delay": 1.0}) + +**Using SetStatus** + +.. code-block:: python + + conn = nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom"}) + nest.SetStatus(conn, {"delay": 1.0}) + +.. code-block:: python + + conn = nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay"}) + nest.SetStatus(conn, {"axonal_delay": 1.0, "dendritic_delay": 1.0}) + +**Using SetDefaults** + +.. code-block:: python + + nest.SetDefaults("stdp_pl_synapse_hom", {"delay": 1.0}) + +.. code-block:: python + + nest.SetDefaults("stdp_pl_synapse_hom_ax_delay", {"axonal_delay": 1.0, "dendritic_delay": 1.0}) + + +.. seealso:: + + :doc:`Example using axonal delays ` + + For details on further developments see :ref:`axonal_delays_dev`. diff --git a/libnestutil/nest_types.h b/libnestutil/nest_types.h index 2e37234248..14ff0d299d 100644 --- a/libnestutil/nest_types.h +++ b/libnestutil/nest_types.h @@ -91,9 +91,15 @@ constexpr uint8_t NUM_BITS_LCID = 27U; constexpr uint8_t NUM_BITS_PROCESSED_FLAG = 1U; constexpr uint8_t NUM_BITS_MARKER_SPIKE_DATA = 2U; constexpr uint8_t NUM_BITS_LAG = 14U; -constexpr uint8_t NUM_BITS_DELAY = 21U; constexpr uint8_t NUM_BITS_NODE_ID = 62U; +// These types are used in delay_types.h and denote the space available for the dendritic and axonal portions of the +// total transmission delay. The delay is only split into two parts for selected synapse types. +// Given that axonal delays can be much larger than dendritic/backpropagation delays, they require more bits. +constexpr uint8_t NUM_BITS_DENDRITIC_DELAY = 14U; +constexpr uint8_t NUM_BITS_AXONAL_DELAY = sizeof( unsigned int ) * 8 - NUM_BITS_DENDRITIC_DELAY; + + // Maximally allowed values for bitfields constexpr uint64_t MAX_LCID = generate_max_value( NUM_BITS_LCID ); diff --git a/models/ac_generator.cpp b/models/ac_generator.cpp index d7c5ea7751..79efcb0a7f 100644 --- a/models/ac_generator.cpp +++ b/models/ac_generator.cpp @@ -56,13 +56,12 @@ RecordablesMap< ac_generator >::create() { insert_( Name( names::I ), &ac_generator::get_I_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameters and state * ---------------------------------------------------------------- */ -nest::ac_generator::Parameters_::Parameters_() +ac_generator::Parameters_::Parameters_() : amp_( 0.0 ) // pA , offset_( 0.0 ) // pA , freq_( 0.0 ) // Hz @@ -70,7 +69,7 @@ nest::ac_generator::Parameters_::Parameters_() { } -nest::ac_generator::Parameters_::Parameters_( const Parameters_& p ) +ac_generator::Parameters_::Parameters_( const Parameters_& p ) : amp_( p.amp_ ) , offset_( p.offset_ ) , freq_( p.freq_ ) @@ -78,8 +77,8 @@ nest::ac_generator::Parameters_::Parameters_( const Parameters_& p ) { } -nest::ac_generator::Parameters_& -nest::ac_generator::Parameters_::operator=( const Parameters_& p ) +ac_generator::Parameters_& +ac_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -94,19 +93,19 @@ nest::ac_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::ac_generator::State_::State_() +ac_generator::State_::State_() : y_0_( 0.0 ) , y_1_( 0.0 ) // pA , I_( 0.0 ) // pA { } -nest::ac_generator::Buffers_::Buffers_( ac_generator& n ) +ac_generator::Buffers_::Buffers_( ac_generator& n ) : logger_( n ) { } -nest::ac_generator::Buffers_::Buffers_( const Buffers_&, ac_generator& n ) +ac_generator::Buffers_::Buffers_( const Buffers_&, ac_generator& n ) : logger_( n ) { } @@ -116,7 +115,7 @@ nest::ac_generator::Buffers_::Buffers_( const Buffers_&, ac_generator& n ) * ---------------------------------------------------------------- */ void -nest::ac_generator::Parameters_::get( DictionaryDatum& d ) const +ac_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::amplitude ] = amp_; ( *d )[ names::offset ] = offset_; @@ -125,14 +124,14 @@ nest::ac_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::ac_generator::State_::get( DictionaryDatum& d ) const +ac_generator::State_::get( DictionaryDatum& d ) const { ( *d )[ names::y_0 ] = y_0_; ( *d )[ names::y_1 ] = y_1_; } void -nest::ac_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +ac_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::amplitude, amp_, node ); updateValueParam< double >( d, names::offset, offset_, node ); @@ -145,7 +144,7 @@ nest::ac_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::ac_generator::ac_generator() +ac_generator::ac_generator() : StimulationDevice() , P_() , S_() @@ -154,7 +153,7 @@ nest::ac_generator::ac_generator() recordablesMap_.create(); } -nest::ac_generator::ac_generator( const ac_generator& n ) +ac_generator::ac_generator( const ac_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -168,20 +167,20 @@ nest::ac_generator::ac_generator( const ac_generator& n ) * ---------------------------------------------------------------- */ void -nest::ac_generator::init_state_() +ac_generator::init_state_() { StimulationDevice::init_state(); } void -nest::ac_generator::init_buffers_() +ac_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); } void -nest::ac_generator::pre_run_hook() +ac_generator::pre_run_hook() { B_.logger_.init(); @@ -206,7 +205,7 @@ nest::ac_generator::pre_run_hook() } void -nest::ac_generator::update( Time const& origin, const long from, const long to ) +ac_generator::update( Time const& origin, const long from, const long to ) { long start = origin.get_steps(); @@ -231,7 +230,7 @@ nest::ac_generator::update( Time const& origin, const long from, const long to ) } void -nest::ac_generator::handle( DataLoggingRequest& e ) +ac_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -241,7 +240,7 @@ nest::ac_generator::handle( DataLoggingRequest& e ) * ---------------------------------------------------------------- */ void -nest::ac_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +ac_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -264,3 +263,5 @@ nest::ac_generator::set_data_from_stimulation_backend( std::vector< double >& in // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/aeif_cond_alpha.cpp b/models/aeif_cond_alpha.cpp index dc8298bc3e..616347a0a4 100644 --- a/models/aeif_cond_alpha.cpp +++ b/models/aeif_cond_alpha.cpp @@ -426,6 +426,8 @@ nest::aeif_cond_alpha::init_buffers_() void nest::aeif_cond_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_cond_alpha_astro.cpp b/models/aeif_cond_alpha_astro.cpp index 9b073b5487..e8e8224b2f 100644 --- a/models/aeif_cond_alpha_astro.cpp +++ b/models/aeif_cond_alpha_astro.cpp @@ -429,6 +429,8 @@ nest::aeif_cond_alpha_astro::init_buffers_() void nest::aeif_cond_alpha_astro::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_cond_alpha_multisynapse.cpp b/models/aeif_cond_alpha_multisynapse.cpp index f027713973..ba018dfe0e 100644 --- a/models/aeif_cond_alpha_multisynapse.cpp +++ b/models/aeif_cond_alpha_multisynapse.cpp @@ -441,6 +441,8 @@ aeif_cond_alpha_multisynapse::init_buffers_() void aeif_cond_alpha_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_cond_beta_multisynapse.cpp b/models/aeif_cond_beta_multisynapse.cpp index 5ef7e10717..7f2eb6f74f 100644 --- a/models/aeif_cond_beta_multisynapse.cpp +++ b/models/aeif_cond_beta_multisynapse.cpp @@ -449,6 +449,8 @@ aeif_cond_beta_multisynapse::init_buffers_() void aeif_cond_beta_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_cond_exp.cpp b/models/aeif_cond_exp.cpp index cb0eb86d0c..470bbc002b 100644 --- a/models/aeif_cond_exp.cpp +++ b/models/aeif_cond_exp.cpp @@ -421,6 +421,8 @@ nest::aeif_cond_exp::init_buffers_() void nest::aeif_cond_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_psc_alpha.cpp b/models/aeif_psc_alpha.cpp index b4a1b9c86e..19117202ee 100644 --- a/models/aeif_psc_alpha.cpp +++ b/models/aeif_psc_alpha.cpp @@ -416,6 +416,8 @@ nest::aeif_psc_alpha::init_buffers_() void nest::aeif_psc_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_psc_delta.cpp b/models/aeif_psc_delta.cpp index 7cafe3ad64..1ff2f245a4 100644 --- a/models/aeif_psc_delta.cpp +++ b/models/aeif_psc_delta.cpp @@ -392,6 +392,8 @@ nest::aeif_psc_delta::init_buffers_() void nest::aeif_psc_delta::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_psc_delta_clopath.cpp b/models/aeif_psc_delta_clopath.cpp index c45158ee77..93fbe91af9 100644 --- a/models/aeif_psc_delta_clopath.cpp +++ b/models/aeif_psc_delta_clopath.cpp @@ -460,6 +460,8 @@ nest::aeif_psc_delta_clopath::init_buffers_() void nest::aeif_psc_delta_clopath::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/aeif_psc_exp.cpp b/models/aeif_psc_exp.cpp index 6b8aec869c..8cbe1b3c85 100644 --- a/models/aeif_psc_exp.cpp +++ b/models/aeif_psc_exp.cpp @@ -411,6 +411,8 @@ nest::aeif_psc_exp::init_buffers_() void nest::aeif_psc_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/amat2_psc_exp.cpp b/models/amat2_psc_exp.cpp index 06bce3bd22..0a111f322e 100644 --- a/models/amat2_psc_exp.cpp +++ b/models/amat2_psc_exp.cpp @@ -264,6 +264,8 @@ nest::amat2_psc_exp::init_buffers_() void nest::amat2_psc_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/bernoulli_synapse.h b/models/bernoulli_synapse.h index 78a6faa963..424723252d 100644 --- a/models/bernoulli_synapse.h +++ b/models/bernoulli_synapse.h @@ -96,12 +96,12 @@ EndUserDocs */ void register_bernoulli_synapse( const std::string& name ); template < typename targetidentifierT > -class bernoulli_synapse : public Connection< targetidentifierT > +class bernoulli_synapse : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -148,10 +148,10 @@ class bernoulli_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } bool diff --git a/models/binary_neuron.h b/models/binary_neuron.h index d3854d650e..4416dc3e15 100644 --- a/models/binary_neuron.h +++ b/models/binary_neuron.h @@ -434,6 +434,8 @@ template < class TGainfunction > void binary_neuron< TGainfunction >::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); V_.rng_ = get_vp_specific_rng( get_thread() ); diff --git a/models/clopath_synapse.h b/models/clopath_synapse.h index 331907f0b2..ba1d976273 100644 --- a/models/clopath_synapse.h +++ b/models/clopath_synapse.h @@ -117,12 +117,12 @@ EndUserDocs */ void register_clopath_synapse( const std::string& name ); template < typename targetidentifierT > -class clopath_synapse : public Connection< targetidentifierT > +class clopath_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::REQUIRES_CLOPATH_ARCHIVING @@ -147,7 +147,7 @@ class clopath_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -184,13 +184,13 @@ class clopath_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -237,11 +237,11 @@ template < typename targetidentifierT > inline bool clopath_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonSynapseProperties& ) { - double t_spike = e.get_stamp().get_ms(); + const double t_spike = e.get_stamp().get_ms(); // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + const double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry_extended >::iterator start; diff --git a/models/cm_default.cpp b/models/cm_default.cpp index 37b714929b..bc93c1b70b 100644 --- a/models/cm_default.cpp +++ b/models/cm_default.cpp @@ -303,6 +303,8 @@ nest::cm_default::init_recordables_pointers_() void nest::cm_default::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + logger_.init(); // initialize the pointers within the compartment tree diff --git a/models/cont_delay_synapse.h b/models/cont_delay_synapse.h index a5759c2622..ebd12cba92 100644 --- a/models/cont_delay_synapse.h +++ b/models/cont_delay_synapse.h @@ -81,12 +81,12 @@ EndUserDocs */ void register_cont_delay_synapse( const std::string& name ); template < typename targetidentifierT > -class cont_delay_synapse : public Connection< targetidentifierT > +class cont_delay_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -115,6 +115,7 @@ class cont_delay_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -198,10 +199,10 @@ class cont_delay_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } private: diff --git a/models/cont_delay_synapse_impl.h b/models/cont_delay_synapse_impl.h index 4a029b82a8..60429ad212 100644 --- a/models/cont_delay_synapse_impl.h +++ b/models/cont_delay_synapse_impl.h @@ -51,7 +51,7 @@ cont_delay_synapse< targetidentifierT >::get_status( DictionaryDatum& d ) const ConnectionBase::get_status( d ); def< double >( d, names::weight, weight_ ); - def< double >( d, names::delay, Time( Time::step( get_delay_steps() ) ).get_ms() - delay_offset_ ); + def< double >( d, names::delay, get_delay_ms() - delay_offset_ ); def< long >( d, names::size_of, sizeof( *this ) ); } diff --git a/models/correlation_detector.cpp b/models/correlation_detector.cpp index 3d7b09b8ae..e8cbb94cd1 100644 --- a/models/correlation_detector.cpp +++ b/models/correlation_detector.cpp @@ -47,11 +47,14 @@ nest::register_correlation_detector( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructors defining default parameters and state * ---------------------------------------------------------------- */ -nest::correlation_detector::Parameters_::Parameters_() +correlation_detector::Parameters_::Parameters_() : delta_tau_( get_default_delta_tau() ) , tau_max_( 10 * delta_tau_ ) , Tstart_( Time::ms( 0.0 ) ) @@ -59,7 +62,7 @@ nest::correlation_detector::Parameters_::Parameters_() { } -nest::correlation_detector::Parameters_::Parameters_( const Parameters_& p ) +correlation_detector::Parameters_::Parameters_( const Parameters_& p ) : delta_tau_( p.delta_tau_ ) , tau_max_( p.tau_max_ ) , Tstart_( p.Tstart_ ) @@ -79,8 +82,8 @@ nest::correlation_detector::Parameters_::Parameters_( const Parameters_& p ) Tstop_.calibrate(); } -nest::correlation_detector::Parameters_& -nest::correlation_detector::Parameters_::operator=( const Parameters_& p ) +correlation_detector::Parameters_& +correlation_detector::Parameters_::operator=( const Parameters_& p ) { delta_tau_ = p.delta_tau_; tau_max_ = p.tau_max_; @@ -95,7 +98,7 @@ nest::correlation_detector::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::correlation_detector::State_::State_() +correlation_detector::State_::State_() : n_events_( 2, 0 ) , incoming_( 2 ) , histogram_() @@ -110,7 +113,7 @@ nest::correlation_detector::State_::State_() * ---------------------------------------------------------------- */ void -nest::correlation_detector::Parameters_::get( DictionaryDatum& d ) const +correlation_detector::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::delta_tau ] = delta_tau_.get_ms(); ( *d )[ names::tau_max ] = tau_max_.get_ms(); @@ -119,7 +122,7 @@ nest::correlation_detector::Parameters_::get( DictionaryDatum& d ) const } void -nest::correlation_detector::State_::get( DictionaryDatum& d ) const +correlation_detector::State_::get( DictionaryDatum& d ) const { ( *d )[ names::n_events ] = IntVectorDatum( new std::vector< long >( n_events_ ) ); ( *d )[ names::histogram ] = DoubleVectorDatum( new std::vector< double >( histogram_ ) ); @@ -128,7 +131,7 @@ nest::correlation_detector::State_::get( DictionaryDatum& d ) const } bool -nest::correlation_detector::Parameters_::set( const DictionaryDatum& d, const correlation_detector& n, Node* node ) +correlation_detector::Parameters_::set( const DictionaryDatum& d, const correlation_detector& n, Node* node ) { bool reset = false; double t; @@ -170,7 +173,7 @@ nest::correlation_detector::Parameters_::set( const DictionaryDatum& d, const co } void -nest::correlation_detector::State_::set( const DictionaryDatum& d, const Parameters_& p, bool reset_required, Node* ) +correlation_detector::State_::set( const DictionaryDatum& d, const Parameters_& p, bool reset_required, Node* ) { std::vector< long > nev; if ( updateValue< std::vector< long > >( d, names::n_events, nev ) ) @@ -191,7 +194,7 @@ nest::correlation_detector::State_::set( const DictionaryDatum& d, const Paramet } void -nest::correlation_detector::State_::reset( const Parameters_& p ) +correlation_detector::State_::reset( const Parameters_& p ) { n_events_.clear(); n_events_.resize( 2, 0 ); @@ -214,7 +217,7 @@ nest::correlation_detector::State_::reset( const Parameters_& p ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::correlation_detector::correlation_detector() +correlation_detector::correlation_detector() : Node() , device_() , P_() @@ -222,7 +225,7 @@ nest::correlation_detector::correlation_detector() { } -nest::correlation_detector::correlation_detector( const correlation_detector& n ) +correlation_detector::correlation_detector( const correlation_detector& n ) : Node( n ) , device_( n.device_ ) , P_( n.P_ ) @@ -236,20 +239,20 @@ nest::correlation_detector::correlation_detector( const correlation_detector& n * ---------------------------------------------------------------- */ void -nest::correlation_detector::init_state_() +correlation_detector::init_state_() { device_.init_state(); } void -nest::correlation_detector::init_buffers_() +correlation_detector::init_buffers_() { device_.init_buffers(); S_.reset( P_ ); } void -nest::correlation_detector::pre_run_hook() +correlation_detector::pre_run_hook() { device_.pre_run_hook(); } @@ -260,12 +263,12 @@ nest::correlation_detector::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::correlation_detector::update( Time const&, const long, const long ) +correlation_detector::update( Time const&, const long, const long ) { } void -nest::correlation_detector::handle( SpikeEvent& e ) +correlation_detector::handle( SpikeEvent& e ) { // The receiver port identifies the sending node in our // sender list. @@ -354,7 +357,7 @@ nest::correlation_detector::handle( SpikeEvent& e ) } void -nest::correlation_detector::calibrate_time( const TimeConverter& tc ) +correlation_detector::calibrate_time( const TimeConverter& tc ) { if ( P_.delta_tau_.is_step() ) { @@ -372,3 +375,5 @@ nest::correlation_detector::calibrate_time( const TimeConverter& tc ) P_.Tstart_ = tc.from_old_tics( P_.Tstart_.get_tics() ); P_.Tstop_ = tc.from_old_tics( P_.Tstop_.get_tics() ); } + +} \ No newline at end of file diff --git a/models/correlomatrix_detector.cpp b/models/correlomatrix_detector.cpp index bab3a03043..66e854b82a 100644 --- a/models/correlomatrix_detector.cpp +++ b/models/correlomatrix_detector.cpp @@ -39,7 +39,6 @@ // Includes from sli: #include "arraydatum.h" #include "dict.h" -#include "dictutils.h" void nest::register_correlomatrix_detector( const std::string& name ) @@ -228,11 +227,11 @@ nest::correlomatrix_detector::State_::reset( const Parameters_& p ) count_covariance_.clear(); count_covariance_.resize( p.N_channels_ ); - for ( long i = 0; i < p.N_channels_; ++i ) + for ( size_t i = 0; i < p.N_channels_; ++i ) { covariance_[ i ].resize( p.N_channels_ ); count_covariance_[ i ].resize( p.N_channels_ ); - for ( long j = 0; j < p.N_channels_; ++j ) + for ( size_t j = 0; j < p.N_channels_; ++j ) { covariance_[ i ][ j ].resize( 1 + p.tau_max_.get_steps() / p.delta_tau_.get_steps(), 0 ); count_covariance_[ i ][ j ].resize( 1 + p.tau_max_.get_steps() / p.delta_tau_.get_steps(), 0 ); @@ -349,8 +348,8 @@ nest::correlomatrix_detector::handle( SpikeEvent& e ) for ( SpikelistType::const_iterator spike_j = otherSpikes.begin(); spike_j != otherSpikes.end(); ++spike_j ) { size_t bin; - long other = spike_j->receptor_channel_; - long sender_ind, other_ind; + size_t other = spike_j->receptor_channel_; + size_t sender_ind, other_ind; if ( spike_i < spike_j->timestep_ ) { diff --git a/models/correlospinmatrix_detector.cpp b/models/correlospinmatrix_detector.cpp index ec270da576..d4c62beb7b 100644 --- a/models/correlospinmatrix_detector.cpp +++ b/models/correlospinmatrix_detector.cpp @@ -41,18 +41,20 @@ #include "dict.h" #include "dictutils.h" +namespace nest +{ + void -nest::register_correlospinmatrix_detector( const std::string& name ) +register_correlospinmatrix_detector( const std::string& name ) { register_node_model< correlospinmatrix_detector >( name ); } - /* ---------------------------------------------------------------- * Default constructors defining default parameters and state * ---------------------------------------------------------------- */ -nest::correlospinmatrix_detector::Parameters_::Parameters_() +correlospinmatrix_detector::Parameters_::Parameters_() : delta_tau_( get_default_delta_tau() ) , tau_max_( 10 * delta_tau_ ) , Tstart_( Time::ms( 0.0 ) ) @@ -61,7 +63,7 @@ nest::correlospinmatrix_detector::Parameters_::Parameters_() { } -nest::correlospinmatrix_detector::Parameters_::Parameters_( const Parameters_& p ) +correlospinmatrix_detector::Parameters_::Parameters_( const Parameters_& p ) : delta_tau_( p.delta_tau_ ) , tau_max_( p.tau_max_ ) , Tstart_( p.Tstart_ ) @@ -83,8 +85,8 @@ nest::correlospinmatrix_detector::Parameters_::Parameters_( const Parameters_& p } -nest::correlospinmatrix_detector::Parameters_& -nest::correlospinmatrix_detector::Parameters_::operator=( const Parameters_& p ) +correlospinmatrix_detector::Parameters_& +correlospinmatrix_detector::Parameters_::operator=( const Parameters_& p ) { delta_tau_ = p.delta_tau_; tau_max_ = p.tau_max_; @@ -101,7 +103,7 @@ nest::correlospinmatrix_detector::Parameters_::operator=( const Parameters_& p ) } -nest::correlospinmatrix_detector::State_::State_() +correlospinmatrix_detector::State_::State_() : incoming_() , last_i_( 0 ) , t_last_in_spike_( Time::neg_inf() ) @@ -115,7 +117,7 @@ nest::correlospinmatrix_detector::State_::State_() * ---------------------------------------------------------------- */ void -nest::correlospinmatrix_detector::Parameters_::get( DictionaryDatum& d ) const +correlospinmatrix_detector::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::delta_tau ] = delta_tau_.get_ms(); ( *d )[ names::tau_max ] = tau_max_.get_ms(); @@ -125,7 +127,7 @@ nest::correlospinmatrix_detector::Parameters_::get( DictionaryDatum& d ) const } void -nest::correlospinmatrix_detector::State_::get( DictionaryDatum& d ) const +correlospinmatrix_detector::State_::get( DictionaryDatum& d ) const { ArrayDatum* CountC = new ArrayDatum; for ( size_t i = 0; i < count_covariance_.size(); ++i ) @@ -141,7 +143,7 @@ nest::correlospinmatrix_detector::State_::get( DictionaryDatum& d ) const } bool -nest::correlospinmatrix_detector::Parameters_::set( const DictionaryDatum& d, +correlospinmatrix_detector::Parameters_::set( const DictionaryDatum& d, const correlospinmatrix_detector& n, Node* node ) { @@ -215,12 +217,12 @@ nest::correlospinmatrix_detector::Parameters_::set( const DictionaryDatum& d, } void -nest::correlospinmatrix_detector::State_::set( const DictionaryDatum&, const Parameters_&, bool, Node* ) +correlospinmatrix_detector::State_::set( const DictionaryDatum&, const Parameters_&, bool, Node* ) { } void -nest::correlospinmatrix_detector::State_::reset( const Parameters_& p ) +correlospinmatrix_detector::State_::reset( const Parameters_& p ) { last_i_ = 0; tentative_down_ = false; @@ -253,7 +255,7 @@ nest::correlospinmatrix_detector::State_::reset( const Parameters_& p ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::correlospinmatrix_detector::correlospinmatrix_detector() +correlospinmatrix_detector::correlospinmatrix_detector() : Node() , device_() , P_() @@ -261,7 +263,7 @@ nest::correlospinmatrix_detector::correlospinmatrix_detector() { } -nest::correlospinmatrix_detector::correlospinmatrix_detector( const correlospinmatrix_detector& n ) +correlospinmatrix_detector::correlospinmatrix_detector( const correlospinmatrix_detector& n ) : Node( n ) , device_( n.device_ ) , P_( n.P_ ) @@ -275,20 +277,20 @@ nest::correlospinmatrix_detector::correlospinmatrix_detector( const correlospinm * ---------------------------------------------------------------- */ void -nest::correlospinmatrix_detector::init_state_() +correlospinmatrix_detector::init_state_() { device_.init_state(); } void -nest::correlospinmatrix_detector::init_buffers_() +correlospinmatrix_detector::init_buffers_() { device_.init_buffers(); S_.reset( P_ ); } void -nest::correlospinmatrix_detector::pre_run_hook() +correlospinmatrix_detector::pre_run_hook() { device_.pre_run_hook(); } @@ -299,12 +301,12 @@ nest::correlospinmatrix_detector::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::correlospinmatrix_detector::update( Time const&, const long, const long ) +correlospinmatrix_detector::update( Time const&, const long, const long ) { } void -nest::correlospinmatrix_detector::handle( SpikeEvent& e ) +correlospinmatrix_detector::handle( SpikeEvent& e ) { // The receiver port identifies the sending node in our // sender list. @@ -392,7 +394,7 @@ nest::correlospinmatrix_detector::handle( SpikeEvent& e ) // yet every impulse in the queue that is further in the past than // this minimum - tau_max cannot contribute to the count covariance long t_min_on = t_i_on; - for ( int n = 0; n < P_.N_channels_; n++ ) + for ( size_t n = 0; n < P_.N_channels_; n++ ) { if ( S_.curr_state_[ n ] ) { @@ -488,7 +490,7 @@ nest::correlospinmatrix_detector::handle( SpikeEvent& e ) } void -nest::correlospinmatrix_detector::calibrate_time( const TimeConverter& tc ) +correlospinmatrix_detector::calibrate_time( const TimeConverter& tc ) { if ( P_.delta_tau_.is_step() ) { @@ -508,3 +510,5 @@ nest::correlospinmatrix_detector::calibrate_time( const TimeConverter& tc ) S_.t_last_in_spike_ = tc.from_old_tics( S_.t_last_in_spike_.get_tics() ); } + +} \ No newline at end of file diff --git a/models/dc_generator.cpp b/models/dc_generator.cpp index 7c5389914f..6e0365d756 100644 --- a/models/dc_generator.cpp +++ b/models/dc_generator.cpp @@ -52,24 +52,23 @@ RecordablesMap< dc_generator >::create() { insert_( Name( names::I ), &dc_generator::get_I_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::dc_generator::Parameters_::Parameters_() +dc_generator::Parameters_::Parameters_() : amp_( 0.0 ) // pA { } -nest::dc_generator::Parameters_::Parameters_( const Parameters_& p ) +dc_generator::Parameters_::Parameters_( const Parameters_& p ) : amp_( p.amp_ ) { } -nest::dc_generator::Parameters_& -nest::dc_generator::Parameters_::operator=( const Parameters_& p ) +dc_generator::Parameters_& +dc_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -81,18 +80,18 @@ nest::dc_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::dc_generator::State_::State_() +dc_generator::State_::State_() : I_( 0.0 ) // pA { } -nest::dc_generator::Buffers_::Buffers_( dc_generator& n ) +dc_generator::Buffers_::Buffers_( dc_generator& n ) : logger_( n ) { } -nest::dc_generator::Buffers_::Buffers_( const Buffers_&, dc_generator& n ) +dc_generator::Buffers_::Buffers_( const Buffers_&, dc_generator& n ) : logger_( n ) { } @@ -102,13 +101,13 @@ nest::dc_generator::Buffers_::Buffers_( const Buffers_&, dc_generator& n ) * ---------------------------------------------------------------- */ void -nest::dc_generator::Parameters_::get( DictionaryDatum& d ) const +dc_generator::Parameters_::get( DictionaryDatum& d ) const { def< double >( d, names::amplitude, amp_ ); } void -nest::dc_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +dc_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::amplitude, amp_, node ); } @@ -118,7 +117,7 @@ nest::dc_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::dc_generator::dc_generator() +dc_generator::dc_generator() : StimulationDevice() , P_() , S_() @@ -127,7 +126,7 @@ nest::dc_generator::dc_generator() recordablesMap_.create(); } -nest::dc_generator::dc_generator( const dc_generator& n ) +dc_generator::dc_generator( const dc_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -140,20 +139,20 @@ nest::dc_generator::dc_generator( const dc_generator& n ) * Node initialization functions * ---------------------------------------------------------------- */ void -nest::dc_generator::init_state_() +dc_generator::init_state_() { StimulationDevice::init_state(); } void -nest::dc_generator::init_buffers_() +dc_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); } void -nest::dc_generator::pre_run_hook() +dc_generator::pre_run_hook() { B_.logger_.init(); @@ -166,7 +165,7 @@ nest::dc_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::dc_generator::update( Time const& origin, const long from, const long to ) +dc_generator::update( Time const& origin, const long from, const long to ) { long start = origin.get_steps(); @@ -185,13 +184,13 @@ nest::dc_generator::update( Time const& origin, const long from, const long to ) } void -nest::dc_generator::handle( DataLoggingRequest& e ) +dc_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } void -nest::dc_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +dc_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -210,3 +209,5 @@ nest::dc_generator::set_data_from_stimulation_backend( std::vector< double >& in // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/diffusion_connection.h b/models/diffusion_connection.h index d7b250853a..75987d86de 100644 --- a/models/diffusion_connection.h +++ b/models/diffusion_connection.h @@ -92,12 +92,12 @@ EndUserDocs */ void register_diffusion_connection( const std::string& name ); template < typename targetidentifierT > -class diffusion_connection : public Connection< targetidentifierT > +class diffusion_connection : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::SUPPORTS_WFR; @@ -125,14 +125,14 @@ class diffusion_connection : public Connection< targetidentifierT > using ConnectionBase::get_target; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { DiffusionConnectionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } /** @@ -165,7 +165,13 @@ class diffusion_connection : public Connection< targetidentifierT > } void - set_delay( double ) + set_delay_ms( double ) + { + throw BadProperty( "diffusion_connection has no delay." ); + } + + void + set_delay_steps( long ) { throw BadProperty( "diffusion_connection has no delay." ); } diff --git a/models/eprop_learning_signal_connection.h b/models/eprop_learning_signal_connection.h index cc013a028b..af7c17d154 100644 --- a/models/eprop_learning_signal_connection.h +++ b/models/eprop_learning_signal_connection.h @@ -130,7 +130,7 @@ void register_eprop_learning_signal_connection( const std::string& name ); * Korcsak-Gorzo, Stapmanns, and Espinoza Valverde et al. (in preparation). */ template < typename targetidentifierT > -class eprop_learning_signal_connection : public Connection< targetidentifierT > +class eprop_learning_signal_connection : public Connection< targetidentifierT, TotalDelay > { public: @@ -138,7 +138,7 @@ class eprop_learning_signal_connection : public Connection< targetidentifierT > typedef CommonSynapseProperties CommonPropertiesType; //! Type of the connection base. - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; //! Properties of the connection model. static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY; @@ -159,14 +159,14 @@ class eprop_learning_signal_connection : public Connection< targetidentifierT > //! Check if the target accepts the event and receptor type requested by the sender. void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex, const CommonPropertiesType& ) { LearningSignalConnectionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } //! Send the learning signal event. diff --git a/models/eprop_learning_signal_connection_bsshslm_2020.h b/models/eprop_learning_signal_connection_bsshslm_2020.h index 5a6f5d5e5d..479ae47c89 100644 --- a/models/eprop_learning_signal_connection_bsshslm_2020.h +++ b/models/eprop_learning_signal_connection_bsshslm_2020.h @@ -133,7 +133,7 @@ void register_eprop_learning_signal_connection_bsshslm_2020( const std::string& * according to Bellec et al. (2020). */ template < typename targetidentifierT > -class eprop_learning_signal_connection_bsshslm_2020 : public Connection< targetidentifierT > +class eprop_learning_signal_connection_bsshslm_2020 : public Connection< targetidentifierT, TotalDelay > { public: @@ -141,7 +141,7 @@ class eprop_learning_signal_connection_bsshslm_2020 : public Connection< targeti typedef CommonSynapseProperties CommonPropertiesType; //! Type of the connection base. - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; //! Properties of the connection model. static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY; @@ -162,14 +162,14 @@ class eprop_learning_signal_connection_bsshslm_2020 : public Connection< targeti //! Check if the target accepts the event and receptor type requested by the sender. void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex, const CommonPropertiesType& ) { LearningSignalConnectionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } //! Send the learning signal event. diff --git a/models/eprop_synapse.h b/models/eprop_synapse.h index 9b4a5679c2..cd1ca076d9 100644 --- a/models/eprop_synapse.h +++ b/models/eprop_synapse.h @@ -223,7 +223,7 @@ void register_eprop_synapse( const std::string& name ); * and default values could be set on it. */ template < typename targetidentifierT > -class eprop_synapse : public Connection< targetidentifierT > +class eprop_synapse : public Connection< targetidentifierT, TotalDelay > { public: @@ -231,7 +231,7 @@ class eprop_synapse : public Connection< targetidentifierT > typedef EpropSynapseCommonProperties CommonPropertiesType; //! Type of the connection base. - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; /** * Properties of the connection model. @@ -260,7 +260,7 @@ class eprop_synapse : public Connection< targetidentifierT > //! Move assignment operator eprop_synapse& operator=( eprop_synapse&& ); - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -298,7 +298,11 @@ class eprop_synapse : public Connection< targetidentifierT > * * @note This sets the optimizer_ member. */ - void check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& cp ); + void check_connection( Node& s, + Node& t, + const size_t receptor_type, + const synindex syn_id, + const CommonPropertiesType& cp ); //! Set the synaptic weight to the provided value. void @@ -460,6 +464,7 @@ inline void eprop_synapse< targetidentifierT >::check_connection( Node& s, Node& t, size_t receptor_type, + const synindex syn_id, const CommonPropertiesType& cp ) { // When we get here, delay has been set so we can check it. @@ -469,7 +474,7 @@ eprop_synapse< targetidentifierT >::check_connection( Node& s, } ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); t.register_eprop_connection(); diff --git a/models/eprop_synapse_bsshslm_2020.h b/models/eprop_synapse_bsshslm_2020.h index 3ac9144827..8b4313083b 100644 --- a/models/eprop_synapse_bsshslm_2020.h +++ b/models/eprop_synapse_bsshslm_2020.h @@ -240,7 +240,7 @@ void register_eprop_synapse_bsshslm_2020( const std::string& name ); * and default values could be set on it. */ template < typename targetidentifierT > -class eprop_synapse_bsshslm_2020 : public Connection< targetidentifierT > +class eprop_synapse_bsshslm_2020 : public Connection< targetidentifierT, TotalDelay > { public: @@ -248,7 +248,7 @@ class eprop_synapse_bsshslm_2020 : public Connection< targetidentifierT > typedef EpropSynapseBSSHSLM2020CommonProperties CommonPropertiesType; //! Type of the connection base. - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; /** * Properties of the connection model. @@ -277,7 +277,7 @@ class eprop_synapse_bsshslm_2020 : public Connection< targetidentifierT > //! Move assignment operator eprop_synapse_bsshslm_2020& operator=( eprop_synapse_bsshslm_2020&& ); - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -315,7 +315,11 @@ class eprop_synapse_bsshslm_2020 : public Connection< targetidentifierT > * * @note This sets the optimizer_ member. */ - void check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& cp ); + void check_connection( Node& s, + Node& t, + const size_t receptor_type, + const synindex syn_id, + const CommonPropertiesType& cp ); //! Set the synaptic weight to the provided value. void @@ -490,6 +494,7 @@ inline void eprop_synapse_bsshslm_2020< targetidentifierT >::check_connection( Node& s, Node& t, size_t receptor_type, + const synindex syn_id, const CommonPropertiesType& cp ) { // When we get here, delay has been set so we can check it. @@ -499,7 +504,7 @@ eprop_synapse_bsshslm_2020< targetidentifierT >::check_connection( Node& s, } ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); t.register_eprop_connection(); @@ -614,8 +619,7 @@ eprop_synapse_bsshslm_2020< targetidentifierT >::set_status( const DictionaryDat kappa_ = std::exp( -Time::get_resolution().get_ms() / tau_m_readout_ ); } - const auto& gcm = - dynamic_cast< const GenericConnectorModel< eprop_synapse_bsshslm_2020< targetidentifierT > >& >( cm ); + const auto& gcm = dynamic_cast< const GenericConnectorModel< eprop_synapse_bsshslm_2020 >& >( cm ); const CommonPropertiesType& epcp = gcm.get_common_properties(); if ( weight_ < epcp.optimizer_cp_->get_Wmin() ) { diff --git a/models/gamma_sup_generator.cpp b/models/gamma_sup_generator.cpp index 5817c36f7f..e99acfbe0a 100644 --- a/models/gamma_sup_generator.cpp +++ b/models/gamma_sup_generator.cpp @@ -45,11 +45,14 @@ nest::register_gamma_sup_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Constructor of internal states class * ---------------------------------------------------------------- */ -nest::gamma_sup_generator::Internal_states_::Internal_states_( size_t num_bins, +gamma_sup_generator::Internal_states_::Internal_states_( size_t num_bins, unsigned long ini_occ_ref, unsigned long ini_occ_act ) { @@ -62,7 +65,7 @@ nest::gamma_sup_generator::Internal_states_::Internal_states_( size_t num_bins, * ---------------------------------------------------------------- */ unsigned long -nest::gamma_sup_generator::Internal_states_::update( double transition_prob, RngPtr rng ) +gamma_sup_generator::Internal_states_::update( double transition_prob, RngPtr rng ) { std::vector< unsigned long > n_trans; // only set from poisson_dist_, bino_dist_ or 0, thus >= 0 n_trans.resize( occ_.size() ); @@ -127,7 +130,7 @@ nest::gamma_sup_generator::Internal_states_::update( double transition_prob, Rng * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::gamma_sup_generator::Parameters_::Parameters_() +gamma_sup_generator::Parameters_::Parameters_() : rate_( 0.0 ) // Hz , gamma_shape_( 1 ) , n_proc_( 1 ) @@ -140,7 +143,7 @@ nest::gamma_sup_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::gamma_sup_generator::Parameters_::get( DictionaryDatum& d ) const +gamma_sup_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_; ( *d )[ names::gamma_shape ] = gamma_shape_; @@ -148,7 +151,7 @@ nest::gamma_sup_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::gamma_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +gamma_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< long >( d, names::gamma_shape, gamma_shape_, node ); if ( gamma_shape_ < 1 ) @@ -179,13 +182,13 @@ nest::gamma_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* nod * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::gamma_sup_generator::gamma_sup_generator() +gamma_sup_generator::gamma_sup_generator() : StimulationDevice() , P_() { } -nest::gamma_sup_generator::gamma_sup_generator( const gamma_sup_generator& n ) +gamma_sup_generator::gamma_sup_generator( const gamma_sup_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) { @@ -197,19 +200,19 @@ nest::gamma_sup_generator::gamma_sup_generator( const gamma_sup_generator& n ) * ---------------------------------------------------------------- */ void -nest::gamma_sup_generator::init_state_() +gamma_sup_generator::init_state_() { StimulationDevice::init_state(); } void -nest::gamma_sup_generator::init_buffers_() +gamma_sup_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::gamma_sup_generator::pre_run_hook() +gamma_sup_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); @@ -234,7 +237,7 @@ nest::gamma_sup_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::gamma_sup_generator::update( Time const& T, const long from, const long to ) +gamma_sup_generator::update( Time const& T, const long from, const long to ) { if ( P_.rate_ <= 0 or P_.num_targets_ == 0 ) { @@ -257,7 +260,7 @@ nest::gamma_sup_generator::update( Time const& T, const long from, const long to void -nest::gamma_sup_generator::event_hook( DSSpikeEvent& e ) +gamma_sup_generator::event_hook( DSSpikeEvent& e ) { // get port number const size_t prt = e.get_port(); @@ -281,7 +284,7 @@ nest::gamma_sup_generator::event_hook( DSSpikeEvent& e ) * ---------------------------------------------------------------- */ void -nest::gamma_sup_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +gamma_sup_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -303,3 +306,5 @@ nest::gamma_sup_generator::set_data_from_stimulation_backend( std::vector< doubl // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/gap_junction.h b/models/gap_junction.h index dd25df9776..cdec0490f0 100644 --- a/models/gap_junction.h +++ b/models/gap_junction.h @@ -84,13 +84,13 @@ EndUserDocs */ void register_gap_junction( const std::string& name ); template < typename targetidentifierT > -class gap_junction : public Connection< targetidentifierT > +class gap_junction : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::REQUIRES_SYMMETRIC | ConnectionModelProperties::SUPPORTS_WFR; @@ -116,14 +116,14 @@ class gap_junction : public Connection< targetidentifierT > using ConnectionBase::get_target; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { GapJunctionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } /** @@ -152,7 +152,13 @@ class gap_junction : public Connection< targetidentifierT > } void - set_delay( double ) + set_delay_ms( double ) + { + throw BadProperty( "gap_junction connection has no delay" ); + } + + void + set_delay_steps( long ) { throw BadProperty( "gap_junction connection has no delay" ); } @@ -168,9 +174,7 @@ template < typename targetidentifierT > void gap_junction< targetidentifierT >::get_status( DictionaryDatum& d ) const { - // We have to include the delay here to prevent - // errors due to internal calls of - // this function in SLI/pyNEST + // We have to include the delay here to prevent errors due to internal calls of this function in SLI/pyNEST ConnectionBase::get_status( d ); def< double >( d, names::weight, weight_ ); def< long >( d, names::size_of, sizeof( *this ) ); @@ -188,7 +192,7 @@ void gap_junction< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) { // If the delay is set, we throw a BadProperty - if ( d->known( names::delay ) ) + if ( d->known( names::delay ) or d->known( names::dendritic_delay ) or d->known( names::axonal_delay ) ) { throw BadProperty( "gap_junction connection has no delay" ); } diff --git a/models/gif_cond_exp.cpp b/models/gif_cond_exp.cpp index 43e7d96d19..fffe6eb9df 100644 --- a/models/gif_cond_exp.cpp +++ b/models/gif_cond_exp.cpp @@ -447,6 +447,8 @@ nest::gif_cond_exp::init_buffers_() void nest::gif_cond_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); diff --git a/models/gif_cond_exp_multisynapse.cpp b/models/gif_cond_exp_multisynapse.cpp index 5a31ba490f..2988f4545b 100644 --- a/models/gif_cond_exp_multisynapse.cpp +++ b/models/gif_cond_exp_multisynapse.cpp @@ -451,6 +451,8 @@ nest::gif_cond_exp_multisynapse::init_buffers_() void nest::gif_cond_exp_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.sys_.dimension = S_.y_.size(); B_.logger_.init(); diff --git a/models/gif_psc_exp.cpp b/models/gif_psc_exp.cpp index 0731dc8175..d7485c7e1a 100644 --- a/models/gif_psc_exp.cpp +++ b/models/gif_psc_exp.cpp @@ -282,6 +282,8 @@ nest::gif_psc_exp::init_buffers_() void nest::gif_psc_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); diff --git a/models/gif_psc_exp_multisynapse.cpp b/models/gif_psc_exp_multisynapse.cpp index cfeca96ea4..ed2fb62550 100644 --- a/models/gif_psc_exp_multisynapse.cpp +++ b/models/gif_psc_exp_multisynapse.cpp @@ -297,6 +297,8 @@ nest::gif_psc_exp_multisynapse::init_buffers_() void nest::gif_psc_exp_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); diff --git a/models/glif_cond.cpp b/models/glif_cond.cpp index a1434786b9..45a43acaa8 100644 --- a/models/glif_cond.cpp +++ b/models/glif_cond.cpp @@ -557,6 +557,8 @@ nest::glif_cond::init_buffers_() void nest::glif_cond::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); // in ms diff --git a/models/glif_psc.cpp b/models/glif_psc.cpp index b60dafc0ec..382947ddee 100644 --- a/models/glif_psc.cpp +++ b/models/glif_psc.cpp @@ -397,6 +397,8 @@ nest::glif_psc::init_buffers_() void nest::glif_psc::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); // in ms diff --git a/models/glif_psc_double_alpha.cpp b/models/glif_psc_double_alpha.cpp index f79de012d3..9f3863e4cd 100644 --- a/models/glif_psc_double_alpha.cpp +++ b/models/glif_psc_double_alpha.cpp @@ -432,6 +432,8 @@ nest::glif_psc_double_alpha::init_buffers_() void nest::glif_psc_double_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); // in ms diff --git a/models/hh_cond_beta_gap_traub.cpp b/models/hh_cond_beta_gap_traub.cpp index 7907b051c8..7fc53f4ac6 100644 --- a/models/hh_cond_beta_gap_traub.cpp +++ b/models/hh_cond_beta_gap_traub.cpp @@ -454,6 +454,8 @@ nest::hh_cond_beta_gap_traub::get_normalisation_factor( double tau_rise, double void nest::hh_cond_beta_gap_traub::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/hh_cond_exp_traub.cpp b/models/hh_cond_exp_traub.cpp index 5aa908a15d..3507c089e0 100644 --- a/models/hh_cond_exp_traub.cpp +++ b/models/hh_cond_exp_traub.cpp @@ -375,6 +375,8 @@ nest::hh_cond_exp_traub::init_buffers_() void nest::hh_cond_exp_traub::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); V_.refractory_counts_ = Time( Time::ms( P_.t_ref_ ) ).get_steps(); diff --git a/models/hh_psc_alpha.cpp b/models/hh_psc_alpha.cpp index 29e953b810..5e4e8d02cf 100644 --- a/models/hh_psc_alpha.cpp +++ b/models/hh_psc_alpha.cpp @@ -373,6 +373,8 @@ nest::hh_psc_alpha::init_buffers_() void nest::hh_psc_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/hh_psc_alpha_clopath.cpp b/models/hh_psc_alpha_clopath.cpp index e0c35e830f..906dfcf71b 100644 --- a/models/hh_psc_alpha_clopath.cpp +++ b/models/hh_psc_alpha_clopath.cpp @@ -401,6 +401,8 @@ nest::hh_psc_alpha_clopath::init_buffers_() void nest::hh_psc_alpha_clopath::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/hh_psc_alpha_gap.cpp b/models/hh_psc_alpha_gap.cpp index b26176784f..9f4aa14e85 100644 --- a/models/hh_psc_alpha_gap.cpp +++ b/models/hh_psc_alpha_gap.cpp @@ -439,6 +439,8 @@ nest::hh_psc_alpha_gap::init_buffers_() void nest::hh_psc_alpha_gap::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/ht_neuron.cpp b/models/ht_neuron.cpp index 047ca61fa3..11aab65c90 100644 --- a/models/ht_neuron.cpp +++ b/models/ht_neuron.cpp @@ -714,6 +714,8 @@ nest::ht_neuron::get_synapse_constant( double tau_1, double tau_2, double g_peak void nest::ht_neuron::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/ht_synapse.h b/models/ht_synapse.h index 1221e89116..004f1d89df 100644 --- a/models/ht_synapse.h +++ b/models/ht_synapse.h @@ -100,11 +100,11 @@ EndUserDocs */ void register_ht_synapse( const std::string& name ); template < typename targetidentifierT > -class ht_synapse : public Connection< targetidentifierT > +class ht_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -126,7 +126,7 @@ class ht_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -169,10 +169,10 @@ class ht_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } //! allows efficient initialization from ConnectorModel::add_connection() diff --git a/models/iaf_bw_2001_exact.cpp b/models/iaf_bw_2001_exact.cpp index 3855c27a53..59f35aaddd 100644 --- a/models/iaf_bw_2001_exact.cpp +++ b/models/iaf_bw_2001_exact.cpp @@ -529,7 +529,7 @@ void nest::iaf_bw_2001_exact::handle( SpikeEvent& e ) { assert( e.get_delay_steps() > 0 ); - assert( e.get_rport() <= static_cast< int >( B_.spikes_.size() ) ); + assert( e.get_rport() <= B_.spikes_.size() ); const double steps = e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ); const auto rport = e.get_rport(); diff --git a/models/iaf_chs_2007.cpp b/models/iaf_chs_2007.cpp index b5c183d7b0..50a4a86d1c 100644 --- a/models/iaf_chs_2007.cpp +++ b/models/iaf_chs_2007.cpp @@ -198,6 +198,8 @@ nest::iaf_chs_2007::init_buffers_() void nest::iaf_chs_2007::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_chxk_2008.cpp b/models/iaf_chxk_2008.cpp index 62559536ae..7ef64dcf3f 100644 --- a/models/iaf_chxk_2008.cpp +++ b/models/iaf_chxk_2008.cpp @@ -344,6 +344,8 @@ nest::iaf_chxk_2008::init_buffers_() void nest::iaf_chxk_2008::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_cond_alpha.cpp b/models/iaf_cond_alpha.cpp index 7cbff968ee..e53a267a5c 100644 --- a/models/iaf_cond_alpha.cpp +++ b/models/iaf_cond_alpha.cpp @@ -358,6 +358,8 @@ nest::iaf_cond_alpha::init_buffers_() void nest::iaf_cond_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_cond_alpha_mc.cpp b/models/iaf_cond_alpha_mc.cpp index 2b99b81025..7fa72fcb3f 100644 --- a/models/iaf_cond_alpha_mc.cpp +++ b/models/iaf_cond_alpha_mc.cpp @@ -558,6 +558,8 @@ nest::iaf_cond_alpha_mc::init_buffers_() void nest::iaf_cond_alpha_mc::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_cond_beta.cpp b/models/iaf_cond_beta.cpp index a0f5d59c2e..c683b4f833 100644 --- a/models/iaf_cond_beta.cpp +++ b/models/iaf_cond_beta.cpp @@ -371,6 +371,8 @@ nest::iaf_cond_beta::get_normalisation_factor( double tau_rise, double tau_decay void nest::iaf_cond_beta::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_cond_exp.cpp b/models/iaf_cond_exp.cpp index c777d686fd..6d6f41a3cc 100644 --- a/models/iaf_cond_exp.cpp +++ b/models/iaf_cond_exp.cpp @@ -336,6 +336,8 @@ nest::iaf_cond_exp::init_buffers_() void nest::iaf_cond_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_cond_exp_sfa_rr.cpp b/models/iaf_cond_exp_sfa_rr.cpp index d37b461e06..b7a26a78c3 100644 --- a/models/iaf_cond_exp_sfa_rr.cpp +++ b/models/iaf_cond_exp_sfa_rr.cpp @@ -372,6 +372,8 @@ nest::iaf_cond_exp_sfa_rr::init_buffers_() void nest::iaf_cond_exp_sfa_rr::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_psc_alpha.cpp b/models/iaf_psc_alpha.cpp index 053a30a22c..79714dfb1f 100644 --- a/models/iaf_psc_alpha.cpp +++ b/models/iaf_psc_alpha.cpp @@ -249,6 +249,8 @@ iaf_psc_alpha::init_buffers_() void iaf_psc_alpha::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); @@ -369,6 +371,7 @@ iaf_psc_alpha::update( Time const& origin, const long from, const long to ) // log state data B_.logger_.record_data( origin.get_steps() + lag ); } + reset_correction_entries_stdp_ax_delay_(); } void @@ -385,6 +388,20 @@ iaf_psc_alpha::handle( SpikeEvent& e ) B_.input_buffer_.add_value( input_buffer_slot, s > 0 ? Buffers_::SYN_EX : Buffers_::SYN_IN, s ); } +void +iaf_psc_alpha::handle( CorrectionSpikeEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + const size_t input_buffer_slot = kernel().event_delivery_manager.get_modulo( + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ) ); + + const double s = ( e.get_new_weight() - e.get_weight() ) * e.get_multiplicity(); + + // separate buffer channels for excitatory and inhibitory inputs + B_.input_buffer_.add_value( input_buffer_slot, e.get_weight() > 0 ? Buffers_::SYN_EX : Buffers_::SYN_IN, s ); +} + void iaf_psc_alpha::handle( CurrentEvent& e ) { diff --git a/models/iaf_psc_alpha.h b/models/iaf_psc_alpha.h index 21d4ff904c..d2b6a62296 100644 --- a/models/iaf_psc_alpha.h +++ b/models/iaf_psc_alpha.h @@ -228,10 +228,12 @@ class iaf_psc_alpha : public ArchivingNode size_t send_test_event( Node&, size_t, synindex, bool ) override; void handle( SpikeEvent& ) override; + void handle( CorrectionSpikeEvent& ) override; void handle( CurrentEvent& ) override; void handle( DataLoggingRequest& ) override; size_t handles_test_event( SpikeEvent&, size_t ) override; + size_t handles_test_event( CorrectionSpikeEvent&, size_t ) override; size_t handles_test_event( CurrentEvent&, size_t ) override; size_t handles_test_event( DataLoggingRequest&, size_t ) override; @@ -432,6 +434,16 @@ iaf_psc_alpha::handles_test_event( SpikeEvent&, size_t receptor_type ) return 0; } +inline size_t +iaf_psc_alpha::handles_test_event( CorrectionSpikeEvent&, size_t receptor_type ) +{ + if ( receptor_type != 0 ) + { + throw UnknownReceptorType( receptor_type, get_name() ); + } + return 0; +} + inline size_t iaf_psc_alpha::handles_test_event( CurrentEvent&, size_t receptor_type ) { diff --git a/models/iaf_psc_alpha_multisynapse.cpp b/models/iaf_psc_alpha_multisynapse.cpp index cee69d2889..916ccc8cfa 100644 --- a/models/iaf_psc_alpha_multisynapse.cpp +++ b/models/iaf_psc_alpha_multisynapse.cpp @@ -290,6 +290,8 @@ iaf_psc_alpha_multisynapse::init_buffers_() void iaf_psc_alpha_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_psc_alpha_ps.cpp b/models/iaf_psc_alpha_ps.cpp index 885d1f2051..14899339b1 100644 --- a/models/iaf_psc_alpha_ps.cpp +++ b/models/iaf_psc_alpha_ps.cpp @@ -264,6 +264,8 @@ nest::iaf_psc_alpha_ps::init_buffers_() void nest::iaf_psc_alpha_ps::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); V_.h_ms_ = Time::get_resolution().get_ms(); diff --git a/models/iaf_psc_delta.cpp b/models/iaf_psc_delta.cpp index 4de329ed60..64c193159e 100644 --- a/models/iaf_psc_delta.cpp +++ b/models/iaf_psc_delta.cpp @@ -236,6 +236,8 @@ nest::iaf_psc_delta::init_buffers_() void nest::iaf_psc_delta::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); diff --git a/models/iaf_psc_delta_ps.cpp b/models/iaf_psc_delta_ps.cpp index 1da42f3dcc..61a612caea 100644 --- a/models/iaf_psc_delta_ps.cpp +++ b/models/iaf_psc_delta_ps.cpp @@ -245,6 +245,8 @@ nest::iaf_psc_delta_ps::init_buffers_() void iaf_psc_delta_ps::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); V_.h_ms_ = Time::get_resolution().get_ms(); diff --git a/models/iaf_psc_exp.cpp b/models/iaf_psc_exp.cpp index 48385040db..a55d68b469 100644 --- a/models/iaf_psc_exp.cpp +++ b/models/iaf_psc_exp.cpp @@ -246,6 +246,8 @@ nest::iaf_psc_exp::init_buffers_() void nest::iaf_psc_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_psc_exp_htum.cpp b/models/iaf_psc_exp_htum.cpp index dd38c565cd..ee4bd1521b 100644 --- a/models/iaf_psc_exp_htum.cpp +++ b/models/iaf_psc_exp_htum.cpp @@ -232,6 +232,8 @@ nest::iaf_psc_exp_htum::init_buffers_() void nest::iaf_psc_exp_htum::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); const double h = Time::get_resolution().get_ms(); diff --git a/models/iaf_psc_exp_multisynapse.cpp b/models/iaf_psc_exp_multisynapse.cpp index 7c53921537..282ca50d6a 100644 --- a/models/iaf_psc_exp_multisynapse.cpp +++ b/models/iaf_psc_exp_multisynapse.cpp @@ -274,6 +274,8 @@ iaf_psc_exp_multisynapse::init_buffers_() void nest::iaf_psc_exp_multisynapse::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_psc_exp_ps.cpp b/models/iaf_psc_exp_ps.cpp index 71f83acc78..275d860108 100644 --- a/models/iaf_psc_exp_ps.cpp +++ b/models/iaf_psc_exp_ps.cpp @@ -253,6 +253,8 @@ nest::iaf_psc_exp_ps::init_buffers_() void nest::iaf_psc_exp_ps::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/iaf_psc_exp_ps_lossless.cpp b/models/iaf_psc_exp_ps_lossless.cpp index dcbf6435bf..a0ea8284d1 100644 --- a/models/iaf_psc_exp_ps_lossless.cpp +++ b/models/iaf_psc_exp_ps_lossless.cpp @@ -278,6 +278,8 @@ nest::iaf_psc_exp_ps_lossless::init_buffers_() void nest::iaf_psc_exp_ps_lossless::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/inhomogeneous_poisson_generator.cpp b/models/inhomogeneous_poisson_generator.cpp index 8f0b5f58ba..3e503f2052 100644 --- a/models/inhomogeneous_poisson_generator.cpp +++ b/models/inhomogeneous_poisson_generator.cpp @@ -48,11 +48,14 @@ nest::register_inhomogeneous_poisson_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::inhomogeneous_poisson_generator::Parameters_::Parameters_() +inhomogeneous_poisson_generator::Parameters_::Parameters_() : rate_times_() // ms , rate_values_() // spikes/ms, , allow_offgrid_times_( false ) @@ -65,7 +68,7 @@ nest::inhomogeneous_poisson_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::inhomogeneous_poisson_generator::Parameters_::get( DictionaryDatum& d ) const +inhomogeneous_poisson_generator::Parameters_::get( DictionaryDatum& d ) const { const size_t n_rates = rate_times_.size(); std::vector< double >* times_ms = new std::vector< double >(); @@ -81,7 +84,7 @@ nest::inhomogeneous_poisson_generator::Parameters_::get( DictionaryDatum& d ) co } void -nest::inhomogeneous_poisson_generator::Parameters_::assert_valid_rate_time_and_insert( const double t ) +inhomogeneous_poisson_generator::Parameters_::assert_valid_rate_time_and_insert( const double t ) { Time t_rate; @@ -117,7 +120,7 @@ nest::inhomogeneous_poisson_generator::Parameters_::assert_valid_rate_time_and_i } void -nest::inhomogeneous_poisson_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) +inhomogeneous_poisson_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) { const bool times = d->known( names::rate_times ); const bool rates = updateValue< std::vector< double > >( d, names::rate_values, rate_values_ ); @@ -196,7 +199,7 @@ nest::inhomogeneous_poisson_generator::Parameters_::set( const DictionaryDatum& * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::inhomogeneous_poisson_generator::inhomogeneous_poisson_generator() +inhomogeneous_poisson_generator::inhomogeneous_poisson_generator() : StimulationDevice() , P_() , B_() @@ -204,7 +207,7 @@ nest::inhomogeneous_poisson_generator::inhomogeneous_poisson_generator() { } -nest::inhomogeneous_poisson_generator::inhomogeneous_poisson_generator( const inhomogeneous_poisson_generator& n ) +inhomogeneous_poisson_generator::inhomogeneous_poisson_generator( const inhomogeneous_poisson_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , B_( n.B_ ) @@ -216,13 +219,13 @@ nest::inhomogeneous_poisson_generator::inhomogeneous_poisson_generator( const in * Node initialization functions * ---------------------------------------------------------------- */ void -nest::inhomogeneous_poisson_generator::init_state_() +inhomogeneous_poisson_generator::init_state_() { StimulationDevice::init_state(); } void -nest::inhomogeneous_poisson_generator::init_buffers_() +inhomogeneous_poisson_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.idx_ = 0; @@ -230,7 +233,7 @@ nest::inhomogeneous_poisson_generator::init_buffers_() } void -nest::inhomogeneous_poisson_generator::pre_run_hook() +inhomogeneous_poisson_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); V_.h_ = Time::get_resolution().get_ms(); @@ -241,7 +244,7 @@ nest::inhomogeneous_poisson_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::inhomogeneous_poisson_generator::update( Time const& origin, const long from, const long to ) +inhomogeneous_poisson_generator::update( Time const& origin, const long from, const long to ) { assert( P_.rate_times_.size() == P_.rate_values_.size() ); @@ -278,7 +281,7 @@ nest::inhomogeneous_poisson_generator::update( Time const& origin, const long fr } void -nest::inhomogeneous_poisson_generator::event_hook( DSSpikeEvent& e ) +inhomogeneous_poisson_generator::event_hook( DSSpikeEvent& e ) { poisson_distribution::param_type param( B_.rate_ * V_.h_ ); long n_spikes = V_.poisson_dist_( get_vp_specific_rng( get_thread() ), param ); @@ -295,7 +298,7 @@ nest::inhomogeneous_poisson_generator::event_hook( DSSpikeEvent& e ) * ---------------------------------------------------------------- */ void -nest::inhomogeneous_poisson_generator::set_data_from_stimulation_backend( std::vector< double >& rate_time_update ) +inhomogeneous_poisson_generator::set_data_from_stimulation_backend( std::vector< double >& rate_time_update ) { Parameters_ ptmp = P_; // temporary copy in case of errors // For the input backend @@ -329,3 +332,5 @@ nest::inhomogeneous_poisson_generator::set_data_from_stimulation_backend( std::v // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/izhikevich.cpp b/models/izhikevich.cpp index 9865f74427..c98e497614 100644 --- a/models/izhikevich.cpp +++ b/models/izhikevich.cpp @@ -184,6 +184,8 @@ nest::izhikevich::init_buffers_() void nest::izhikevich::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); } diff --git a/models/jonke_synapse.h b/models/jonke_synapse.h index e8bb578566..2def725129 100644 --- a/models/jonke_synapse.h +++ b/models/jonke_synapse.h @@ -165,12 +165,12 @@ class JonkeCommonProperties : public CommonSynapseProperties void register_jonke_synapse( const std::string& name ); template < typename targetidentifierT > -class jonke_synapse : public Connection< targetidentifierT > +class jonke_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef JonkeCommonProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -194,7 +194,7 @@ class jonke_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -231,13 +231,13 @@ class jonke_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -306,7 +306,7 @@ jonke_synapse< targetidentifierT >::send( Event& e, size_t t, const JonkeCommonP // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/mat2_psc_exp.cpp b/models/mat2_psc_exp.cpp index 104d20af0f..441144acdc 100644 --- a/models/mat2_psc_exp.cpp +++ b/models/mat2_psc_exp.cpp @@ -243,6 +243,8 @@ nest::mat2_psc_exp::init_buffers_() void nest::mat2_psc_exp::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); diff --git a/models/mip_generator.cpp b/models/mip_generator.cpp index bf60516e97..9d6790e053 100644 --- a/models/mip_generator.cpp +++ b/models/mip_generator.cpp @@ -39,11 +39,14 @@ nest::register_mip_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::mip_generator::Parameters_::Parameters_() +mip_generator::Parameters_::Parameters_() : rate_( 0.0 ) // spks/s , p_copy_( 1.0 ) { @@ -54,14 +57,14 @@ nest::mip_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::mip_generator::Parameters_::get( DictionaryDatum& d ) const +mip_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_; ( *d )[ names::p_copy ] = p_copy_; } void -nest::mip_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +mip_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::rate, rate_, node ); updateValueParam< double >( d, names::p_copy, p_copy_, node ); @@ -81,13 +84,13 @@ nest::mip_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::mip_generator::mip_generator() +mip_generator::mip_generator() : StimulationDevice() , P_() { } -nest::mip_generator::mip_generator( const mip_generator& n ) +mip_generator::mip_generator( const mip_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) // also causes deep copy of random nnumber generator { @@ -98,19 +101,19 @@ nest::mip_generator::mip_generator( const mip_generator& n ) * ---------------------------------------------------------------- */ void -nest::mip_generator::init_state_() +mip_generator::init_state_() { StimulationDevice::init_state(); } void -nest::mip_generator::init_buffers_() +mip_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::mip_generator::pre_run_hook() +mip_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); @@ -125,7 +128,7 @@ nest::mip_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::mip_generator::update( Time const& T, const long from, const long to ) +mip_generator::update( Time const& T, const long from, const long to ) { for ( long lag = from; lag < to; ++lag ) { @@ -148,7 +151,7 @@ nest::mip_generator::update( Time const& T, const long from, const long to ) } void -nest::mip_generator::event_hook( DSSpikeEvent& e ) +mip_generator::event_hook( DSSpikeEvent& e ) { /* We temporarily set the spike multiplicity here to the number of @@ -186,7 +189,7 @@ nest::mip_generator::event_hook( DSSpikeEvent& e ) * Other functions * ---------------------------------------------------------------- */ void -nest::mip_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +mip_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -209,3 +212,5 @@ nest::mip_generator::set_data_from_stimulation_backend( std::vector< double >& i // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest diff --git a/models/noise_generator.cpp b/models/noise_generator.cpp index 7bc72369da..804e4c62fe 100644 --- a/models/noise_generator.cpp +++ b/models/noise_generator.cpp @@ -55,13 +55,12 @@ RecordablesMap< noise_generator >::create() { insert_( Name( names::I ), &noise_generator::get_I_avg_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::noise_generator::Parameters_::Parameters_() +noise_generator::Parameters_::Parameters_() : mean_( 0.0 ) // pA , std_( 0.0 ) // pA / sqrt(s) , std_mod_( 0.0 ) // pA / sqrt(s) @@ -72,7 +71,7 @@ nest::noise_generator::Parameters_::Parameters_() { } -nest::noise_generator::Parameters_::Parameters_( const Parameters_& p ) +noise_generator::Parameters_::Parameters_( const Parameters_& p ) : mean_( p.mean_ ) , std_( p.std_ ) , std_mod_( p.std_mod_ ) @@ -91,8 +90,8 @@ nest::noise_generator::Parameters_::Parameters_( const Parameters_& p ) } } -nest::noise_generator::Parameters_& -nest::noise_generator::Parameters_::operator=( const Parameters_& p ) +noise_generator::Parameters_& +noise_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -109,20 +108,20 @@ nest::noise_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::noise_generator::State_::State_() +noise_generator::State_::State_() : y_0_( 0.0 ) , y_1_( 0.0 ) // pA , I_avg_( 0.0 ) // pA { } -nest::noise_generator::Buffers_::Buffers_( noise_generator& n ) +noise_generator::Buffers_::Buffers_( noise_generator& n ) : next_step_( 0 ) , logger_( n ) { } -nest::noise_generator::Buffers_::Buffers_( const Buffers_& b, noise_generator& n ) +noise_generator::Buffers_::Buffers_( const Buffers_& b, noise_generator& n ) : next_step_( b.next_step_ ) , logger_( n ) { @@ -133,7 +132,7 @@ nest::noise_generator::Buffers_::Buffers_( const Buffers_& b, noise_generator& n * ---------------------------------------------------------------- */ void -nest::noise_generator::Parameters_::get( DictionaryDatum& d ) const +noise_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::mean ] = mean_; ( *d )[ names::std ] = std_; @@ -144,14 +143,14 @@ nest::noise_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::noise_generator::State_::get( DictionaryDatum& d ) const +noise_generator::State_::get( DictionaryDatum& d ) const { ( *d )[ names::y_0 ] = y_0_; ( *d )[ names::y_1 ] = y_1_; } void -nest::noise_generator::Parameters_::set( const DictionaryDatum& d, const noise_generator& n, Node* node ) +noise_generator::Parameters_::set( const DictionaryDatum& d, const noise_generator& n, Node* node ) { updateValueParam< double >( d, names::mean, mean_, node ); updateValueParam< double >( d, names::std, std_, node ); @@ -189,7 +188,7 @@ nest::noise_generator::Parameters_::set( const DictionaryDatum& d, const noise_g * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::noise_generator::noise_generator() +noise_generator::noise_generator() : StimulationDevice() , P_() , S_() @@ -198,7 +197,7 @@ nest::noise_generator::noise_generator() recordablesMap_.create(); } -nest::noise_generator::noise_generator( const noise_generator& n ) +noise_generator::noise_generator( const noise_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -212,13 +211,13 @@ nest::noise_generator::noise_generator( const noise_generator& n ) * ---------------------------------------------------------------- */ void -nest::noise_generator::init_state_() +noise_generator::init_state_() { StimulationDevice::init_state(); } void -nest::noise_generator::init_buffers_() +noise_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); @@ -229,7 +228,7 @@ nest::noise_generator::init_buffers_() } void -nest::noise_generator::pre_run_hook() +noise_generator::pre_run_hook() { B_.logger_.init(); @@ -266,7 +265,7 @@ nest::noise_generator::pre_run_hook() * ---------------------------------------------------------------- */ size_t -nest::noise_generator::send_test_event( Node& target, size_t receptor_type, synindex syn_id, bool dummy_target ) +noise_generator::send_test_event( Node& target, size_t receptor_type, synindex syn_id, bool dummy_target ) { StimulationDevice::enforce_single_syn_type( syn_id ); @@ -293,7 +292,7 @@ nest::noise_generator::send_test_event( Node& target, size_t receptor_type, syni // Time Evolution Operator // void -nest::noise_generator::update( Time const& origin, const long from, const long to ) +noise_generator::update( Time const& origin, const long from, const long to ) { const long start = origin.get_steps(); @@ -344,7 +343,7 @@ nest::noise_generator::update( Time const& origin, const long from, const long t } void -nest::noise_generator::event_hook( DSCurrentEvent& e ) +noise_generator::event_hook( DSCurrentEvent& e ) { // get port number const size_t prt = e.get_port(); @@ -357,7 +356,7 @@ nest::noise_generator::event_hook( DSCurrentEvent& e ) } void -nest::noise_generator::handle( DataLoggingRequest& e ) +noise_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -367,7 +366,7 @@ nest::noise_generator::handle( DataLoggingRequest& e ) * ---------------------------------------------------------------- */ void -nest::noise_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +noise_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors ptmp.num_targets_ = P_.num_targets_; @@ -395,7 +394,7 @@ nest::noise_generator::set_data_from_stimulation_backend( std::vector< double >& } void -nest::noise_generator::calibrate_time( const TimeConverter& tc ) +noise_generator::calibrate_time( const TimeConverter& tc ) { if ( P_.dt_.is_step() ) { @@ -409,3 +408,5 @@ nest::noise_generator::calibrate_time( const TimeConverter& tc ) LOG( M_INFO, get_name(), msg ); } } + +} // namespace nest \ No newline at end of file diff --git a/models/poisson_generator.cpp b/models/poisson_generator.cpp index 516a886bca..9cb2278fb9 100644 --- a/models/poisson_generator.cpp +++ b/models/poisson_generator.cpp @@ -36,18 +36,21 @@ #include "dictutils.h" #include "doubledatum.h" + +namespace nest +{ + void -nest::register_poisson_generator( const std::string& name ) +register_poisson_generator( const std::string& name ) { register_node_model< poisson_generator >( name ); } - /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::poisson_generator::Parameters_::Parameters_() +poisson_generator::Parameters_::Parameters_() : rate_( 0.0 ) // spks/s { } @@ -58,13 +61,13 @@ nest::poisson_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::poisson_generator::Parameters_::get( DictionaryDatum& d ) const +poisson_generator::Parameters_::get( DictionaryDatum& d ) const { def< double >( d, names::rate, rate_ ); } void -nest::poisson_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +poisson_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::rate, rate_, node ); if ( rate_ < 0 ) @@ -78,13 +81,13 @@ nest::poisson_generator::Parameters_::set( const DictionaryDatum& d, Node* node * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::poisson_generator::poisson_generator() +poisson_generator::poisson_generator() : StimulationDevice() , P_() { } -nest::poisson_generator::poisson_generator( const poisson_generator& n ) +poisson_generator::poisson_generator( const poisson_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) { @@ -96,19 +99,19 @@ nest::poisson_generator::poisson_generator( const poisson_generator& n ) * ---------------------------------------------------------------- */ void -nest::poisson_generator::init_state_() +poisson_generator::init_state_() { StimulationDevice::init_state(); } void -nest::poisson_generator::init_buffers_() +poisson_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::poisson_generator::pre_run_hook() +poisson_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); @@ -123,7 +126,7 @@ nest::poisson_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::poisson_generator::update( Time const& T, const long from, const long to ) +poisson_generator::update( Time const& T, const long from, const long to ) { if ( P_.rate_ <= 0 ) { @@ -143,7 +146,7 @@ nest::poisson_generator::update( Time const& T, const long from, const long to ) } void -nest::poisson_generator::event_hook( DSSpikeEvent& e ) +poisson_generator::event_hook( DSSpikeEvent& e ) { long n_spikes = V_.poisson_dist_( get_vp_specific_rng( get_thread() ) ); @@ -159,7 +162,7 @@ nest::poisson_generator::event_hook( DSSpikeEvent& e ) * ---------------------------------------------------------------- */ void -nest::poisson_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +poisson_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -178,3 +181,5 @@ nest::poisson_generator::set_data_from_stimulation_backend( std::vector< double // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} diff --git a/models/poisson_generator_ps.cpp b/models/poisson_generator_ps.cpp index 7a913d15bc..a44302dfe2 100644 --- a/models/poisson_generator_ps.cpp +++ b/models/poisson_generator_ps.cpp @@ -46,11 +46,14 @@ nest::register_poisson_generator_ps( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::poisson_generator_ps::Parameters_::Parameters_() +poisson_generator_ps::Parameters_::Parameters_() : rate_( 0.0 ) // spks/s , dead_time_( 0.0 ) // ms , num_targets_( 0 ) @@ -62,14 +65,14 @@ nest::poisson_generator_ps::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::poisson_generator_ps::Parameters_::get( DictionaryDatum& d ) const +poisson_generator_ps::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_; ( *d )[ names::dead_time ] = dead_time_; } void -nest::poisson_generator_ps::Parameters_::set( const DictionaryDatum& d, Node* node ) +poisson_generator_ps::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::dead_time, dead_time_, node ); if ( dead_time_ < 0 ) @@ -95,13 +98,13 @@ nest::poisson_generator_ps::Parameters_::set( const DictionaryDatum& d, Node* no * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::poisson_generator_ps::poisson_generator_ps() +poisson_generator_ps::poisson_generator_ps() : StimulationDevice() , P_() { } -nest::poisson_generator_ps::poisson_generator_ps( const poisson_generator_ps& n ) +poisson_generator_ps::poisson_generator_ps( const poisson_generator_ps& n ) : StimulationDevice( n ) , P_( n.P_ ) { @@ -113,15 +116,15 @@ nest::poisson_generator_ps::poisson_generator_ps( const poisson_generator_ps& n * ---------------------------------------------------------------- */ void -nest::poisson_generator_ps::init_state_() +poisson_generator_ps::init_state_() { StimulationDevice::init_state(); } void -nest::poisson_generator_ps::init_buffers_() +poisson_generator_ps::init_buffers_() { - nest::Device::init_buffers(); + Device::init_buffers(); // forget all about past, but do not discard connection information B_.next_spike_.clear(); @@ -129,7 +132,7 @@ nest::poisson_generator_ps::init_buffers_() } void -nest::poisson_generator_ps::pre_run_hook() +poisson_generator_ps::pre_run_hook() { StimulationDevice::pre_run_hook(); if ( P_.rate_ > 0 ) @@ -182,7 +185,7 @@ nest::poisson_generator_ps::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::poisson_generator_ps::update( Time const& T, const long from, const long to ) +poisson_generator_ps::update( Time const& T, const long from, const long to ) { if ( P_.rate_ <= 0 or P_.num_targets_ == 0 ) { @@ -210,7 +213,7 @@ nest::poisson_generator_ps::update( Time const& T, const long from, const long t } void -nest::poisson_generator_ps::event_hook( DSSpikeEvent& e ) +poisson_generator_ps::event_hook( DSSpikeEvent& e ) { // get port number const size_t prt = e.get_port(); @@ -284,7 +287,7 @@ nest::poisson_generator_ps::event_hook( DSSpikeEvent& e ) } void -nest::poisson_generator_ps::set_data_from_stimulation_backend( std::vector< double >& input_param ) +poisson_generator_ps::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -304,3 +307,5 @@ nest::poisson_generator_ps::set_data_from_stimulation_backend( std::vector< doub // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest diff --git a/models/pp_cond_exp_mc_urbanczik.cpp b/models/pp_cond_exp_mc_urbanczik.cpp index 04d58df15f..54f775f491 100644 --- a/models/pp_cond_exp_mc_urbanczik.cpp +++ b/models/pp_cond_exp_mc_urbanczik.cpp @@ -560,6 +560,8 @@ nest::pp_cond_exp_mc_urbanczik::init_buffers_() void nest::pp_cond_exp_mc_urbanczik::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + // ensures initialization in case mm connected after Simulate B_.logger_.init(); V_.rng_ = get_vp_specific_rng( get_thread() ); diff --git a/models/pp_psc_delta.cpp b/models/pp_psc_delta.cpp index 482fde1dff..e165c99b35 100644 --- a/models/pp_psc_delta.cpp +++ b/models/pp_psc_delta.cpp @@ -294,6 +294,8 @@ nest::pp_psc_delta::init_buffers_() void nest::pp_psc_delta::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); V_.h_ = Time::get_resolution().get_ms(); diff --git a/models/ppd_sup_generator.cpp b/models/ppd_sup_generator.cpp index 32eb092145..e4724d7b36 100644 --- a/models/ppd_sup_generator.cpp +++ b/models/ppd_sup_generator.cpp @@ -45,11 +45,14 @@ nest::register_ppd_sup_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Constructor of age distribution class * ---------------------------------------------------------------- */ -nest::ppd_sup_generator::Age_distribution_::Age_distribution_( size_t num_age_bins, +ppd_sup_generator::Age_distribution_::Age_distribution_( size_t num_age_bins, unsigned long ini_occ_ref, unsigned long ini_occ_act ) { @@ -63,7 +66,7 @@ nest::ppd_sup_generator::Age_distribution_::Age_distribution_( size_t num_age_bi * ---------------------------------------------------------------- */ unsigned long -nest::ppd_sup_generator::Age_distribution_::update( double hazard_step, RngPtr rng ) +ppd_sup_generator::Age_distribution_::update( double hazard_step, RngPtr rng ) { unsigned long n_spikes; // only set from poisson_dev, bino_dev or 0, thus >= 0 if ( occ_active_ > 0 ) @@ -110,7 +113,7 @@ nest::ppd_sup_generator::Age_distribution_::update( double hazard_step, RngPtr r * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::ppd_sup_generator::Parameters_::Parameters_() +ppd_sup_generator::Parameters_::Parameters_() : rate_( 0.0 ) // Hz , dead_time_( 0.0 ) // ms , n_proc_( 1 ) @@ -125,7 +128,7 @@ nest::ppd_sup_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::ppd_sup_generator::Parameters_::get( DictionaryDatum& d ) const +ppd_sup_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_; ( *d )[ names::dead_time ] = dead_time_; @@ -135,7 +138,7 @@ nest::ppd_sup_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::ppd_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) +ppd_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::dead_time, dead_time_, node ); if ( dead_time_ < 0 ) @@ -174,13 +177,13 @@ nest::ppd_sup_generator::Parameters_::set( const DictionaryDatum& d, Node* node * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::ppd_sup_generator::ppd_sup_generator() +ppd_sup_generator::ppd_sup_generator() : StimulationDevice() , P_() { } -nest::ppd_sup_generator::ppd_sup_generator( const ppd_sup_generator& n ) +ppd_sup_generator::ppd_sup_generator( const ppd_sup_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) { @@ -192,19 +195,19 @@ nest::ppd_sup_generator::ppd_sup_generator( const ppd_sup_generator& n ) * ---------------------------------------------------------------- */ void -nest::ppd_sup_generator::init_state_() +ppd_sup_generator::init_state_() { StimulationDevice::init_state(); } void -nest::ppd_sup_generator::init_buffers_() +ppd_sup_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::ppd_sup_generator::pre_run_hook() +ppd_sup_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); @@ -235,7 +238,7 @@ nest::ppd_sup_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::ppd_sup_generator::update( Time const& T, const long from, const long to ) +ppd_sup_generator::update( Time const& T, const long from, const long to ) { if ( P_.rate_ <= 0 or P_.num_targets_ == 0 ) { @@ -269,7 +272,7 @@ nest::ppd_sup_generator::update( Time const& T, const long from, const long to ) void -nest::ppd_sup_generator::event_hook( DSSpikeEvent& e ) +ppd_sup_generator::event_hook( DSSpikeEvent& e ) { // get port number const size_t prt = e.get_port(); @@ -294,7 +297,7 @@ nest::ppd_sup_generator::event_hook( DSSpikeEvent& e ) * ---------------------------------------------------------------- */ void -nest::ppd_sup_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +ppd_sup_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -319,3 +322,5 @@ nest::ppd_sup_generator::set_data_from_stimulation_backend( std::vector< double // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/pulsepacket_generator.cpp b/models/pulsepacket_generator.cpp index 19b4db16c6..e609128907 100644 --- a/models/pulsepacket_generator.cpp +++ b/models/pulsepacket_generator.cpp @@ -47,11 +47,14 @@ nest::register_pulsepacket_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructors defining default parameters and variables * ---------------------------------------------------------------- */ -nest::pulsepacket_generator::Parameters_::Parameters_() +pulsepacket_generator::Parameters_::Parameters_() : pulse_times_() , a_( 0 ) , sdev_( 0.0 ) @@ -59,7 +62,7 @@ nest::pulsepacket_generator::Parameters_::Parameters_() { } -nest::pulsepacket_generator::Variables_::Variables_() +pulsepacket_generator::Variables_::Variables_() : start_center_idx_( 0 ) , stop_center_idx_( 0 ) , tolerance( 0.0 ) @@ -71,7 +74,7 @@ nest::pulsepacket_generator::Variables_::Variables_() * ---------------------------------------------------------------- */ void -nest::pulsepacket_generator::Parameters_::get( DictionaryDatum& d ) const +pulsepacket_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::pulse_times ] = DoubleVectorDatum( new std::vector< double >( pulse_times_ ) ); ( *d )[ names::activity ] = a_; @@ -79,7 +82,7 @@ nest::pulsepacket_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::pulsepacket_generator::Parameters_::set( const DictionaryDatum& d, pulsepacket_generator& ppg, Node* node ) +pulsepacket_generator::Parameters_::set( const DictionaryDatum& d, pulsepacket_generator& ppg, Node* node ) { // We cannot use a single line here since short-circuiting may stop evaluation // prematurely. Therefore, neednewpulse must be second arg on second line. @@ -106,13 +109,13 @@ nest::pulsepacket_generator::Parameters_::set( const DictionaryDatum& d, pulsepa * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::pulsepacket_generator::pulsepacket_generator() +pulsepacket_generator::pulsepacket_generator() : StimulationDevice() , P_() { } -nest::pulsepacket_generator::pulsepacket_generator( const pulsepacket_generator& ppg ) +pulsepacket_generator::pulsepacket_generator( const pulsepacket_generator& ppg ) : StimulationDevice( ppg ) , P_( ppg.P_ ) { @@ -123,19 +126,19 @@ nest::pulsepacket_generator::pulsepacket_generator( const pulsepacket_generator& * ---------------------------------------------------------------- */ void -nest::pulsepacket_generator::init_state_() +pulsepacket_generator::init_state_() { StimulationDevice::init_state(); } void -nest::pulsepacket_generator::init_buffers_() +pulsepacket_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::pulsepacket_generator::pre_run_hook() +pulsepacket_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); assert( V_.start_center_idx_ <= V_.stop_center_idx_ ); @@ -170,7 +173,7 @@ nest::pulsepacket_generator::pre_run_hook() void -nest::pulsepacket_generator::update( Time const& T, const long, const long to ) +pulsepacket_generator::update( Time const& T, const long, const long to ) { if ( ( V_.start_center_idx_ == P_.pulse_times_.size() and B_.spiketimes_.empty() ) or ( not StimulationDevice::is_active( T ) ) ) @@ -238,7 +241,7 @@ nest::pulsepacket_generator::update( Time const& T, const long, const long to ) * ---------------------------------------------------------------- */ void -nest::pulsepacket_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +pulsepacket_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -262,3 +265,5 @@ nest::pulsepacket_generator::set_data_from_stimulation_backend( std::vector< dou // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/quantal_stp_synapse.h b/models/quantal_stp_synapse.h index 3c866a3674..f33cbb10fe 100644 --- a/models/quantal_stp_synapse.h +++ b/models/quantal_stp_synapse.h @@ -109,11 +109,11 @@ EndUserDocs */ void register_quantal_stp_synapse( const std::string& name ); template < typename targetidentifierT > -class quantal_stp_synapse : public Connection< targetidentifierT > +class quantal_stp_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -135,7 +135,7 @@ class quantal_stp_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -172,10 +172,10 @@ class quantal_stp_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } void diff --git a/models/rate_connection_delayed.h b/models/rate_connection_delayed.h index 81c3f3ea40..433d5c5214 100644 --- a/models/rate_connection_delayed.h +++ b/models/rate_connection_delayed.h @@ -79,13 +79,13 @@ EndUserDocs */ void register_rate_connection_delayed( const std::string& name ); template < typename targetidentifierT > -class rate_connection_delayed : public Connection< targetidentifierT > +class rate_connection_delayed : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY; @@ -112,14 +112,14 @@ class rate_connection_delayed : public Connection< targetidentifierT > using ConnectionBase::get_target; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { DelayedRateConnectionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } /** diff --git a/models/rate_connection_instantaneous.h b/models/rate_connection_instantaneous.h index 4d32e41cc0..083d63da1d 100644 --- a/models/rate_connection_instantaneous.h +++ b/models/rate_connection_instantaneous.h @@ -80,13 +80,13 @@ EndUserDocs */ void register_rate_connection_instantaneous( const std::string& name ); template < typename targetidentifierT > -class rate_connection_instantaneous : public Connection< targetidentifierT > +class rate_connection_instantaneous : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::SUPPORTS_WFR; @@ -113,14 +113,14 @@ class rate_connection_instantaneous : public Connection< targetidentifierT > using ConnectionBase::get_target; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { InstantaneousRateConnectionEvent ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } /** @@ -149,11 +149,15 @@ class rate_connection_instantaneous : public Connection< targetidentifierT > } void - set_delay( double ) + set_delay_ms( double ) { - throw BadProperty( - "rate_connection_instantaneous has no delay. Please use " - "rate_connection_delayed." ); + throw BadProperty( "rate_connection_instantaneous has no delay. Please use rate_connection_delayed." ); + } + + void + set_delay_steps( long ) + { + throw BadProperty( "rate_connection_instantaneous has no delay. Please use rate_connection_delayed." ); } private: @@ -179,9 +183,7 @@ rate_connection_instantaneous< targetidentifierT >::set_status( const Dictionary // If the delay is set, we throw a BadProperty if ( d->known( names::delay ) ) { - throw BadProperty( - "rate_connection_instantaneous has no delay. Please use " - "rate_connection_delayed." ); + throw BadProperty( "rate_connection_instantaneous has no delay. Please use rate_connection_delayed." ); } ConnectionBase::set_status( d, cm ); diff --git a/models/rate_neuron_ipn_impl.h b/models/rate_neuron_ipn_impl.h index 286c22c0af..96286bffa2 100644 --- a/models/rate_neuron_ipn_impl.h +++ b/models/rate_neuron_ipn_impl.h @@ -63,7 +63,7 @@ RecordablesMap< rate_neuron_ipn< TNonlinearities > > rate_neuron_ipn< TNonlinear * ---------------------------------------------------------------- */ template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::Parameters_::Parameters_() +rate_neuron_ipn< TNonlinearities >::Parameters_::Parameters_() : tau_( 10.0 ) // ms , lambda_( 1.0 ) // ms , sigma_( 1.0 ) @@ -77,7 +77,7 @@ nest::rate_neuron_ipn< TNonlinearities >::Parameters_::Parameters_() } template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::State_::State_() +rate_neuron_ipn< TNonlinearities >::State_::State_() : rate_( 0.0 ) , noise_( 0.0 ) { @@ -89,7 +89,7 @@ nest::rate_neuron_ipn< TNonlinearities >::State_::State_() template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const +rate_neuron_ipn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const { def< double >( d, names::tau, tau_ ); def< double >( d, names::lambda, lambda_ ); @@ -107,7 +107,7 @@ nest::rate_neuron_ipn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) +rate_neuron_ipn< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::tau, tau_, node ); updateValueParam< double >( d, names::lambda, lambda_, node ); @@ -156,7 +156,7 @@ nest::rate_neuron_ipn< TNonlinearities >::Parameters_::set( const DictionaryDatu template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::State_::get( DictionaryDatum& d ) const +rate_neuron_ipn< TNonlinearities >::State_::get( DictionaryDatum& d ) const { def< double >( d, names::rate, rate_ ); // Rate def< double >( d, names::noise, noise_ ); // Noise @@ -164,19 +164,19 @@ nest::rate_neuron_ipn< TNonlinearities >::State_::get( DictionaryDatum& d ) cons template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) +rate_neuron_ipn< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::rate, rate_, node ); // Rate } template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( rate_neuron_ipn< TNonlinearities >& n ) +rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( rate_neuron_ipn< TNonlinearities >& n ) : logger_( n ) { } template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_ipn< TNonlinearities >& n ) +rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_ipn< TNonlinearities >& n ) : logger_( n ) { } @@ -186,7 +186,7 @@ nest::rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, r * ---------------------------------------------------------------- */ template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn() +rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn() : ArchivingNode() , P_() , S_() @@ -197,7 +197,7 @@ nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn() } template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn( const rate_neuron_ipn& n ) +rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn( const rate_neuron_ipn& n ) : ArchivingNode( n ) , nonlinearities_( n.nonlinearities_ ) , P_( n.P_ ) @@ -213,7 +213,7 @@ nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn( const rate_neuron_ipn template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::init_buffers_() +rate_neuron_ipn< TNonlinearities >::init_buffers_() { B_.delayed_rates_ex_.clear(); // includes resize B_.delayed_rates_in_.clear(); // includes resize @@ -237,8 +237,10 @@ nest::rate_neuron_ipn< TNonlinearities >::init_buffers_() template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::pre_run_hook() +rate_neuron_ipn< TNonlinearities >::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); // ensures initialization in case mm connected after Simulate const double h = Time::get_resolution().get_ms(); @@ -265,7 +267,7 @@ nest::rate_neuron_ipn< TNonlinearities >::pre_run_hook() template < class TNonlinearities > bool -nest::rate_neuron_ipn< TNonlinearities >::update_( Time const& origin, +rate_neuron_ipn< TNonlinearities >::update_( Time const& origin, const long from, const long to, const bool called_from_wfr_update ) @@ -394,7 +396,7 @@ nest::rate_neuron_ipn< TNonlinearities >::update_( Time const& origin, template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) +rate_neuron_ipn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) { const double weight = e.get_weight(); @@ -431,7 +433,7 @@ nest::rate_neuron_ipn< TNonlinearities >::handle( InstantaneousRateConnectionEve template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) +rate_neuron_ipn< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) { const double weight = e.get_weight(); const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay(); @@ -469,7 +471,7 @@ nest::rate_neuron_ipn< TNonlinearities >::handle( DelayedRateConnectionEvent& e template < class TNonlinearities > void -nest::rate_neuron_ipn< TNonlinearities >::handle( DataLoggingRequest& e ) +rate_neuron_ipn< TNonlinearities >::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } diff --git a/models/rate_neuron_opn_impl.h b/models/rate_neuron_opn_impl.h index 2479fe8c23..5bfe69c1ef 100644 --- a/models/rate_neuron_opn_impl.h +++ b/models/rate_neuron_opn_impl.h @@ -223,6 +223,8 @@ template < class TNonlinearities > void nest::rate_neuron_opn< TNonlinearities >::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); // ensures initialization in case mm connected after Simulate const double h = Time::get_resolution().get_ms(); diff --git a/models/rate_transformer_node_impl.h b/models/rate_transformer_node_impl.h index 2809b97130..b4823cbf67 100644 --- a/models/rate_transformer_node_impl.h +++ b/models/rate_transformer_node_impl.h @@ -167,6 +167,8 @@ template < class TNonlinearities > void nest::rate_transformer_node< TNonlinearities >::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); // ensures initialization in case mm connected after Simulate } diff --git a/models/sic_connection.h b/models/sic_connection.h index 0cf806c2ac..7b94abbd20 100644 --- a/models/sic_connection.h +++ b/models/sic_connection.h @@ -66,13 +66,13 @@ EndUserDocs */ void register_sic_connection( const std::string& name ); template < typename targetidentifierT > -class sic_connection : public Connection< targetidentifierT > +class sic_connection : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; typedef SICEvent EventType; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY; @@ -97,14 +97,14 @@ class sic_connection : public Connection< targetidentifierT > using ConnectionBase::get_target; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex, const CommonPropertiesType& ) { EventType ge; s.sends_secondary_event( ge ); ge.set_sender( s ); - Connection< targetidentifierT >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); - Connection< targetidentifierT >::target_.set_target( &t ); + Connection< targetidentifierT, TotalDelay >::target_.set_rport( t.handles_test_event( ge, receptor_type ) ); + Connection< targetidentifierT, TotalDelay >::target_.set_target( &t ); } /** diff --git a/models/siegert_neuron.cpp b/models/siegert_neuron.cpp index ec39ab5cec..895b78f569 100644 --- a/models/siegert_neuron.cpp +++ b/models/siegert_neuron.cpp @@ -296,6 +296,8 @@ nest::siegert_neuron::init_buffers_() void nest::siegert_neuron::pre_run_hook() { + ArchivingNode::pre_run_hook_(); + B_.logger_.init(); // ensures initialization in case mm connected after Simulate const double h = Time::get_resolution().get_ms(); diff --git a/models/sinusoidal_gamma_generator.cpp b/models/sinusoidal_gamma_generator.cpp index 30c49fe411..1b7399ed6e 100644 --- a/models/sinusoidal_gamma_generator.cpp +++ b/models/sinusoidal_gamma_generator.cpp @@ -47,14 +47,16 @@ #include "dictutils.h" #include "doubledatum.h" -namespace nest -{ + void -register_sinusoidal_gamma_generator( const std::string& name ) +nest::register_sinusoidal_gamma_generator( const std::string& name ) { register_node_model< sinusoidal_gamma_generator >( name ); } +namespace nest +{ + RecordablesMap< sinusoidal_gamma_generator > sinusoidal_gamma_generator::recordablesMap_; template <> @@ -63,10 +65,8 @@ RecordablesMap< sinusoidal_gamma_generator >::create() { insert_( names::rate, &sinusoidal_gamma_generator::get_rate_ ); } -} - -nest::sinusoidal_gamma_generator::Parameters_::Parameters_() +sinusoidal_gamma_generator::Parameters_::Parameters_() : om_( 0.0 ) // radian/ms , phi_( 0.0 ) // radian , order_( 1.0 ) @@ -77,7 +77,7 @@ nest::sinusoidal_gamma_generator::Parameters_::Parameters_() { } -nest::sinusoidal_gamma_generator::Parameters_::Parameters_( const Parameters_& p ) +sinusoidal_gamma_generator::Parameters_::Parameters_( const Parameters_& p ) : om_( p.om_ ) , phi_( p.phi_ ) , order_( p.order_ ) @@ -88,8 +88,8 @@ nest::sinusoidal_gamma_generator::Parameters_::Parameters_( const Parameters_& p { } -nest::sinusoidal_gamma_generator::Parameters_& -nest::sinusoidal_gamma_generator::Parameters_::operator=( const Parameters_& p ) +sinusoidal_gamma_generator::Parameters_& +sinusoidal_gamma_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -107,13 +107,13 @@ nest::sinusoidal_gamma_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::sinusoidal_gamma_generator::State_::State_() +sinusoidal_gamma_generator::State_::State_() : rate_( 0 ) { } -nest::sinusoidal_gamma_generator::Buffers_::Buffers_( sinusoidal_gamma_generator& n ) +sinusoidal_gamma_generator::Buffers_::Buffers_( sinusoidal_gamma_generator& n ) : logger_( n ) , t0_ms_() , // will be set in init_buffers_ @@ -123,7 +123,7 @@ nest::sinusoidal_gamma_generator::Buffers_::Buffers_( sinusoidal_gamma_generator { } -nest::sinusoidal_gamma_generator::Buffers_::Buffers_( const Buffers_& b, sinusoidal_gamma_generator& n ) +sinusoidal_gamma_generator::Buffers_::Buffers_( const Buffers_& b, sinusoidal_gamma_generator& n ) : logger_( n ) , t0_ms_( b.t0_ms_ ) , Lambda_t0_( b.Lambda_t0_ ) @@ -136,7 +136,7 @@ nest::sinusoidal_gamma_generator::Buffers_::Buffers_( const Buffers_& b, sinusoi * ---------------------------------------------------------------- */ void -nest::sinusoidal_gamma_generator::Parameters_::get( DictionaryDatum& d ) const +sinusoidal_gamma_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_ * 1000.0; ( *d )[ names::frequency ] = om_ / ( 2.0 * numerics::pi / 1000.0 ); @@ -147,7 +147,7 @@ nest::sinusoidal_gamma_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::sinusoidal_gamma_generator::Parameters_::set( const DictionaryDatum& d, +sinusoidal_gamma_generator::Parameters_::set( const DictionaryDatum& d, const sinusoidal_gamma_generator& n, Node* node ) { @@ -217,7 +217,7 @@ nest::sinusoidal_gamma_generator::Parameters_::set( const DictionaryDatum& d, * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::sinusoidal_gamma_generator::sinusoidal_gamma_generator() +sinusoidal_gamma_generator::sinusoidal_gamma_generator() : StimulationDevice() , P_() , S_() @@ -226,7 +226,7 @@ nest::sinusoidal_gamma_generator::sinusoidal_gamma_generator() recordablesMap_.create(); } -nest::sinusoidal_gamma_generator::sinusoidal_gamma_generator( const sinusoidal_gamma_generator& n ) +sinusoidal_gamma_generator::sinusoidal_gamma_generator( const sinusoidal_gamma_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -239,13 +239,13 @@ nest::sinusoidal_gamma_generator::sinusoidal_gamma_generator( const sinusoidal_g * ---------------------------------------------------------------- */ void -nest::sinusoidal_gamma_generator::init_state_() +sinusoidal_gamma_generator::init_state_() { StimulationDevice::init_state(); } void -nest::sinusoidal_gamma_generator::init_buffers_() +sinusoidal_gamma_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); @@ -258,7 +258,7 @@ nest::sinusoidal_gamma_generator::init_buffers_() // ---------------------------------------------------- inline double -nest::sinusoidal_gamma_generator::deltaLambda_( const Parameters_& p, double t_a, double t_b ) const +sinusoidal_gamma_generator::deltaLambda_( const Parameters_& p, double t_a, double t_b ) const { if ( t_a == t_b ) { @@ -277,7 +277,7 @@ nest::sinusoidal_gamma_generator::deltaLambda_( const Parameters_& p, double t_a // ---------------------------------------------------- void -nest::sinusoidal_gamma_generator::pre_run_hook() +sinusoidal_gamma_generator::pre_run_hook() { // ensures initialization in case mm connected after Simulate B_.logger_.init(); @@ -304,7 +304,7 @@ nest::sinusoidal_gamma_generator::pre_run_hook() } double -nest::sinusoidal_gamma_generator::hazard_( size_t tgt_idx ) const +sinusoidal_gamma_generator::hazard_( size_t tgt_idx ) const { // Note: We compute Lambda for the entire interval since the last spike/ // parameter change each time for better accuracy. @@ -314,7 +314,7 @@ nest::sinusoidal_gamma_generator::hazard_( size_t tgt_idx ) const } void -nest::sinusoidal_gamma_generator::update( Time const& origin, const long from, const long to ) +sinusoidal_gamma_generator::update( Time const& origin, const long from, const long to ) { for ( long lag = from; lag < to; ++lag ) { @@ -348,7 +348,7 @@ nest::sinusoidal_gamma_generator::update( Time const& origin, const long from, c } void -nest::sinusoidal_gamma_generator::event_hook( DSSpikeEvent& e ) +sinusoidal_gamma_generator::event_hook( DSSpikeEvent& e ) { // get port number --- see #737 const size_t tgt_idx = e.get_port(); @@ -363,7 +363,7 @@ nest::sinusoidal_gamma_generator::event_hook( DSSpikeEvent& e ) } void -nest::sinusoidal_gamma_generator::handle( DataLoggingRequest& e ) +sinusoidal_gamma_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -373,7 +373,7 @@ nest::sinusoidal_gamma_generator::handle( DataLoggingRequest& e ) * ---------------------------------------------------------------- */ void -nest::sinusoidal_gamma_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +sinusoidal_gamma_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -399,4 +399,7 @@ nest::sinusoidal_gamma_generator::set_data_from_stimulation_backend( std::vector // if we get here, temporary contains consistent set of properties P_ = ptmp; } -#endif // HAVE_GSL + +} // namespace nest + +#endif // HAVE_GSL \ No newline at end of file diff --git a/models/sinusoidal_poisson_generator.cpp b/models/sinusoidal_poisson_generator.cpp index 6a24cfae5f..f7b87b170d 100644 --- a/models/sinusoidal_poisson_generator.cpp +++ b/models/sinusoidal_poisson_generator.cpp @@ -59,13 +59,12 @@ RecordablesMap< sinusoidal_poisson_generator >::create() { insert_( Name( names::rate ), &sinusoidal_poisson_generator::get_rate_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::sinusoidal_poisson_generator::Parameters_::Parameters_() +sinusoidal_poisson_generator::Parameters_::Parameters_() : om_( 0.0 ) // radian/ms , phi_( 0.0 ) // radian , rate_( 0.0 ) // spikes/ms @@ -74,7 +73,7 @@ nest::sinusoidal_poisson_generator::Parameters_::Parameters_() { } -nest::sinusoidal_poisson_generator::Parameters_::Parameters_( const Parameters_& p ) +sinusoidal_poisson_generator::Parameters_::Parameters_( const Parameters_& p ) : om_( p.om_ ) , phi_( p.phi_ ) , rate_( p.rate_ ) @@ -83,8 +82,8 @@ nest::sinusoidal_poisson_generator::Parameters_::Parameters_( const Parameters_& { } -nest::sinusoidal_poisson_generator::Parameters_& -nest::sinusoidal_poisson_generator::Parameters_::operator=( const Parameters_& p ) +sinusoidal_poisson_generator::Parameters_& +sinusoidal_poisson_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -100,7 +99,7 @@ nest::sinusoidal_poisson_generator::Parameters_::operator=( const Parameters_& p return *this; } -nest::sinusoidal_poisson_generator::State_::State_() +sinusoidal_poisson_generator::State_::State_() : y_0_( 0 ) , y_1_( 0 ) , rate_( 0 ) @@ -108,12 +107,12 @@ nest::sinusoidal_poisson_generator::State_::State_() } -nest::sinusoidal_poisson_generator::Buffers_::Buffers_( sinusoidal_poisson_generator& n ) +sinusoidal_poisson_generator::Buffers_::Buffers_( sinusoidal_poisson_generator& n ) : logger_( n ) { } -nest::sinusoidal_poisson_generator::Buffers_::Buffers_( const Buffers_&, sinusoidal_poisson_generator& n ) +sinusoidal_poisson_generator::Buffers_::Buffers_( const Buffers_&, sinusoidal_poisson_generator& n ) : logger_( n ) { } @@ -124,7 +123,7 @@ nest::sinusoidal_poisson_generator::Buffers_::Buffers_( const Buffers_&, sinusoi * ---------------------------------------------------------------- */ void -nest::sinusoidal_poisson_generator::Parameters_::get( DictionaryDatum& d ) const +sinusoidal_poisson_generator::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::rate ] = rate_ * 1000.0; ( *d )[ names::frequency ] = om_ / ( 2.0 * numerics::pi / 1000.0 ); @@ -134,14 +133,14 @@ nest::sinusoidal_poisson_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::sinusoidal_poisson_generator::State_::get( DictionaryDatum& d ) const +sinusoidal_poisson_generator::State_::get( DictionaryDatum& d ) const { ( *d )[ names::y_0 ] = y_0_; ( *d )[ names::y_1 ] = y_1_; } void -nest::sinusoidal_poisson_generator::Parameters_::set( const DictionaryDatum& d, +sinusoidal_poisson_generator::Parameters_::set( const DictionaryDatum& d, const sinusoidal_poisson_generator& n, Node* node ) { @@ -179,7 +178,7 @@ nest::sinusoidal_poisson_generator::Parameters_::set( const DictionaryDatum& d, * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::sinusoidal_poisson_generator::sinusoidal_poisson_generator() +sinusoidal_poisson_generator::sinusoidal_poisson_generator() : StimulationDevice() , P_() , S_() @@ -188,7 +187,7 @@ nest::sinusoidal_poisson_generator::sinusoidal_poisson_generator() recordablesMap_.create(); } -nest::sinusoidal_poisson_generator::sinusoidal_poisson_generator( const sinusoidal_poisson_generator& n ) +sinusoidal_poisson_generator::sinusoidal_poisson_generator( const sinusoidal_poisson_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -201,20 +200,20 @@ nest::sinusoidal_poisson_generator::sinusoidal_poisson_generator( const sinusoid * ---------------------------------------------------------------- */ void -nest::sinusoidal_poisson_generator::init_state_() +sinusoidal_poisson_generator::init_state_() { StimulationDevice::init_state(); } void -nest::sinusoidal_poisson_generator::init_buffers_() +sinusoidal_poisson_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); } void -nest::sinusoidal_poisson_generator::pre_run_hook() +sinusoidal_poisson_generator::pre_run_hook() { // ensures initialization in case mm connected after Simulate B_.logger_.init(); @@ -234,7 +233,7 @@ nest::sinusoidal_poisson_generator::pre_run_hook() } void -nest::sinusoidal_poisson_generator::update( Time const& origin, const long from, const long to ) +sinusoidal_poisson_generator::update( Time const& origin, const long from, const long to ) { const long start = origin.get_steps(); @@ -287,7 +286,7 @@ nest::sinusoidal_poisson_generator::update( Time const& origin, const long from, } void -nest::sinusoidal_poisson_generator::event_hook( DSSpikeEvent& e ) +sinusoidal_poisson_generator::event_hook( DSSpikeEvent& e ) { poisson_distribution::param_type param( S_.rate_ * V_.h_ ); long n_spikes = V_.poisson_dist_( get_vp_specific_rng( get_thread() ), param ); @@ -300,7 +299,7 @@ nest::sinusoidal_poisson_generator::event_hook( DSSpikeEvent& e ) } void -nest::sinusoidal_poisson_generator::handle( DataLoggingRequest& e ) +sinusoidal_poisson_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -310,7 +309,7 @@ nest::sinusoidal_poisson_generator::handle( DataLoggingRequest& e ) * ---------------------------------------------------------------- */ void -nest::sinusoidal_poisson_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) +sinusoidal_poisson_generator::set_data_from_stimulation_backend( std::vector< double >& input_param ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -335,3 +334,5 @@ nest::sinusoidal_poisson_generator::set_data_from_stimulation_backend( std::vect // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest diff --git a/models/spike_dilutor.cpp b/models/spike_dilutor.cpp index b4d105a70d..bd63cb7490 100644 --- a/models/spike_dilutor.cpp +++ b/models/spike_dilutor.cpp @@ -36,18 +36,20 @@ #include "dict.h" #include "dictutils.h" +namespace nest +{ + void -nest::register_spike_dilutor( const std::string& name ) +register_spike_dilutor( const std::string& name ) { register_node_model< spike_dilutor >( name ); } - /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::spike_dilutor::Parameters_::Parameters_() +spike_dilutor::Parameters_::Parameters_() : p_copy_( 1.0 ) { } @@ -57,13 +59,13 @@ nest::spike_dilutor::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::spike_dilutor::Parameters_::get( DictionaryDatum& d ) const +spike_dilutor::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::p_copy ] = p_copy_; } void -nest::spike_dilutor::Parameters_::set( const DictionaryDatum& d, Node* node ) +spike_dilutor::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< double >( d, names::p_copy, p_copy_, node ); if ( p_copy_ < 0 or p_copy_ > 1 ) @@ -76,14 +78,14 @@ nest::spike_dilutor::Parameters_::set( const DictionaryDatum& d, Node* node ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::spike_dilutor::spike_dilutor() +spike_dilutor::spike_dilutor() : DeviceNode() , device_() , P_() { } -nest::spike_dilutor::spike_dilutor( const spike_dilutor& n ) +spike_dilutor::spike_dilutor( const spike_dilutor& n ) : DeviceNode( n ) , device_( n.device_ ) , P_( n.P_ ) @@ -95,7 +97,7 @@ nest::spike_dilutor::spike_dilutor( const spike_dilutor& n ) * ---------------------------------------------------------------- */ void -nest::spike_dilutor::init_state_() +spike_dilutor::init_state_() { // This check cannot be done in the copy constructor because that is also used to // create model prototypes. Since spike_dilutor is deprecated anyways, we put this @@ -109,14 +111,14 @@ nest::spike_dilutor::init_state_() } void -nest::spike_dilutor::init_buffers_() +spike_dilutor::init_buffers_() { B_.n_spikes_.clear(); // includes resize device_.init_buffers(); } void -nest::spike_dilutor::pre_run_hook() +spike_dilutor::pre_run_hook() { device_.pre_run_hook(); } @@ -126,7 +128,7 @@ nest::spike_dilutor::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::spike_dilutor::update( Time const& T, const long from, const long to ) +spike_dilutor::update( Time const& T, const long from, const long to ) { for ( long lag = from; lag < to; ++lag ) { @@ -149,7 +151,7 @@ nest::spike_dilutor::update( Time const& T, const long from, const long to ) } void -nest::spike_dilutor::event_hook( DSSpikeEvent& e ) +spike_dilutor::event_hook( DSSpikeEvent& e ) { // Note: event_hook() receives a reference of the spike event that // was originally created in the update function. There we set @@ -182,8 +184,10 @@ nest::spike_dilutor::event_hook( DSSpikeEvent& e ) } void -nest::spike_dilutor::handle( SpikeEvent& e ) +spike_dilutor::handle( SpikeEvent& e ) { B_.n_spikes_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), static_cast< double >( e.get_multiplicity() ) ); } + +} // namespace nest \ No newline at end of file diff --git a/models/spike_generator.cpp b/models/spike_generator.cpp index c6153ede4c..99fa5f1b4d 100644 --- a/models/spike_generator.cpp +++ b/models/spike_generator.cpp @@ -44,11 +44,14 @@ nest::register_spike_generator( const std::string& name ) } +namespace nest +{ + /* ---------------------------------------------------------------- * Default constructor defining default parameters * ---------------------------------------------------------------- */ -nest::spike_generator::Parameters_::Parameters_() +spike_generator::Parameters_::Parameters_() : spike_stamps_() , spike_offsets_() , spike_weights_() @@ -65,7 +68,7 @@ nest::spike_generator::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::spike_generator::Parameters_::get( DictionaryDatum& d ) const +spike_generator::Parameters_::get( DictionaryDatum& d ) const { const size_t n_spikes = spike_stamps_.size(); auto* times_ms = new std::vector< double >(); @@ -89,7 +92,7 @@ nest::spike_generator::Parameters_::get( DictionaryDatum& d ) const } void -nest::spike_generator::Parameters_::assert_valid_spike_time_and_insert_( double t, const Time& origin, const Time& now ) +spike_generator::Parameters_::assert_valid_spike_time_and_insert_( double t, const Time& origin, const Time& now ) { if ( t == 0.0 and not shift_now_spikes_ ) { @@ -154,7 +157,7 @@ nest::spike_generator::Parameters_::assert_valid_spike_time_and_insert_( double } void -nest::spike_generator::Parameters_::set( const DictionaryDatum& d, +spike_generator::Parameters_::set( const DictionaryDatum& d, State_& s, const Time& origin, const Time& now, @@ -275,7 +278,7 @@ nest::spike_generator::Parameters_::set( const DictionaryDatum& d, * Default constructor defining default state * ---------------------------------------------------------------- */ -nest::spike_generator::State_::State_() +spike_generator::State_::State_() : position_( 0 ) { } @@ -285,14 +288,14 @@ nest::spike_generator::State_::State_() * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::spike_generator::spike_generator() +spike_generator::spike_generator() : StimulationDevice() , P_() , S_() { } -nest::spike_generator::spike_generator( const spike_generator& n ) +spike_generator::spike_generator( const spike_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -305,19 +308,19 @@ nest::spike_generator::spike_generator( const spike_generator& n ) * ---------------------------------------------------------------- */ void -nest::spike_generator::init_state_() +spike_generator::init_state_() { StimulationDevice::init_state(); } void -nest::spike_generator::init_buffers_() +spike_generator::init_buffers_() { StimulationDevice::init_buffers(); } void -nest::spike_generator::pre_run_hook() +spike_generator::pre_run_hook() { StimulationDevice::pre_run_hook(); } @@ -327,7 +330,7 @@ nest::spike_generator::pre_run_hook() * Other functions * ---------------------------------------------------------------- */ void -nest::spike_generator::update( Time const& sliceT0, const long from, const long to ) +spike_generator::update( Time const& sliceT0, const long from, const long to ) { if ( P_.spike_stamps_.empty() ) { @@ -397,7 +400,7 @@ nest::spike_generator::update( Time const& sliceT0, const long from, const long } void -nest::spike_generator::event_hook( DSSpikeEvent& e ) +spike_generator::event_hook( DSSpikeEvent& e ) { e.set_weight( P_.spike_weights_[ S_.position_ ] * e.get_weight() ); e.get_receiver().handle( e ); @@ -409,7 +412,7 @@ nest::spike_generator::event_hook( DSSpikeEvent& e ) * ---------------------------------------------------------------- */ void -nest::spike_generator::set_data_from_stimulation_backend( std::vector< double >& input_spikes ) +spike_generator::set_data_from_stimulation_backend( std::vector< double >& input_spikes ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -440,3 +443,5 @@ nest::spike_generator::set_data_from_stimulation_backend( std::vector< double >& // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/spike_recorder.cpp b/models/spike_recorder.cpp index 5769fa60e7..fae95004f5 100644 --- a/models/spike_recorder.cpp +++ b/models/spike_recorder.cpp @@ -36,43 +36,47 @@ #include "dict.h" #include "dictutils.h" + +namespace nest +{ + void -nest::register_spike_recorder( const std::string& name ) +register_spike_recorder( const std::string& name ) { register_node_model< spike_recorder >( name ); } -nest::spike_recorder::spike_recorder() +spike_recorder::spike_recorder() : RecordingDevice() { } -nest::spike_recorder::spike_recorder( const spike_recorder& n ) +spike_recorder::spike_recorder( const spike_recorder& n ) : RecordingDevice( n ) { } void -nest::spike_recorder::pre_run_hook() +spike_recorder::pre_run_hook() { RecordingDevice::pre_run_hook( RecordingBackend::NO_DOUBLE_VALUE_NAMES, RecordingBackend::NO_LONG_VALUE_NAMES ); } void -nest::spike_recorder::update( Time const&, const long, const long ) +spike_recorder::update( Time const&, const long, const long ) { // Nothing to do. Writing to the backend happens in handle(). } -nest::RecordingDevice::Type -nest::spike_recorder::get_type() const +RecordingDevice::Type +spike_recorder::get_type() const { return RecordingDevice::SPIKE_RECORDER; } void -nest::spike_recorder::get_status( DictionaryDatum& d ) const +spike_recorder::get_status( DictionaryDatum& d ) const { RecordingDevice::get_status( d ); @@ -94,13 +98,13 @@ nest::spike_recorder::get_status( DictionaryDatum& d ) const } void -nest::spike_recorder::set_status( const DictionaryDatum& d ) +spike_recorder::set_status( const DictionaryDatum& d ) { RecordingDevice::set_status( d ); } void -nest::spike_recorder::handle( SpikeEvent& e ) +spike_recorder::handle( SpikeEvent& e ) { // accept spikes only if detector was active when spike was emitted if ( is_active( e.get_stamp() ) ) @@ -113,3 +117,5 @@ nest::spike_recorder::handle( SpikeEvent& e ) } } } + +} // namespace nest \ No newline at end of file diff --git a/models/spin_detector.cpp b/models/spin_detector.cpp index 190ece15cb..ca76c674e4 100644 --- a/models/spin_detector.cpp +++ b/models/spin_detector.cpp @@ -36,20 +36,22 @@ #include "dict.h" #include "dictutils.h" +namespace nest +{ + void -nest::register_spin_detector( const std::string& name ) +register_spin_detector( const std::string& name ) { register_node_model< spin_detector >( name ); } - -nest::spin_detector::spin_detector() +spin_detector::spin_detector() : last_in_node_id_( 0 ) , t_last_in_spike_( Time::neg_inf() ) { } -nest::spin_detector::spin_detector( const spin_detector& n ) +spin_detector::spin_detector( const spin_detector& n ) : RecordingDevice( n ) , last_in_node_id_( 0 ) , t_last_in_spike_( Time::neg_inf() ) // mark as not initialized @@ -57,18 +59,18 @@ nest::spin_detector::spin_detector( const spin_detector& n ) } void -nest::spin_detector::init_buffers_() +spin_detector::init_buffers_() { } void -nest::spin_detector::pre_run_hook() +spin_detector::pre_run_hook() { - RecordingDevice::pre_run_hook( RecordingBackend::NO_DOUBLE_VALUE_NAMES, { nest::names::state } ); + RecordingDevice::pre_run_hook( RecordingBackend::NO_DOUBLE_VALUE_NAMES, { names::state } ); } void -nest::spin_detector::update( Time const&, const long, const long ) +spin_detector::update( Time const&, const long, const long ) { if ( last_in_node_id_ != 0 ) // if last_* is empty we dont write { @@ -77,14 +79,14 @@ nest::spin_detector::update( Time const&, const long, const long ) } } -nest::RecordingDevice::Type -nest::spin_detector::get_type() const +RecordingDevice::Type +spin_detector::get_type() const { return RecordingDevice::SPIN_DETECTOR; } void -nest::spin_detector::get_status( DictionaryDatum& d ) const +spin_detector::get_status( DictionaryDatum& d ) const { // get the data from the device RecordingDevice::get_status( d ); @@ -108,14 +110,14 @@ nest::spin_detector::get_status( DictionaryDatum& d ) const } void -nest::spin_detector::set_status( const DictionaryDatum& d ) +spin_detector::set_status( const DictionaryDatum& d ) { RecordingDevice::set_status( d ); } void -nest::spin_detector::handle( SpikeEvent& e ) +spin_detector::handle( SpikeEvent& e ) { // accept spikes only if detector was active when spike was // emitted @@ -170,3 +172,5 @@ nest::spin_detector::handle( SpikeEvent& e ) } } } + +} // namespace nest \ No newline at end of file diff --git a/models/spin_detector.h b/models/spin_detector.h index 2cb2ef1775..05e4dcd243 100644 --- a/models/spin_detector.h +++ b/models/spin_detector.h @@ -180,7 +180,7 @@ spin_detector::receives_signal() const } inline void -nest::spin_detector::calibrate_time( const TimeConverter& tc ) +spin_detector::calibrate_time( const TimeConverter& tc ) { t_last_in_spike_ = tc.from_old_tics( t_last_in_spike_.get_tics() ); } diff --git a/models/static_synapse.h b/models/static_synapse.h index 25ebf2ce61..e049114ab3 100644 --- a/models/static_synapse.h +++ b/models/static_synapse.h @@ -63,14 +63,14 @@ EndUserDocs */ void register_static_synapse( const std::string& name ); template < typename targetidentifierT > -class static_synapse : public Connection< targetidentifierT > +class static_synapse : public Connection< targetidentifierT, TotalDelay > { double weight_; public: // this line determines which common properties to use typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -151,10 +151,10 @@ class static_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } bool diff --git a/models/static_synapse_hom_w.h b/models/static_synapse_hom_w.h index f6ea22c3df..66a1b9ee00 100644 --- a/models/static_synapse_hom_w.h +++ b/models/static_synapse_hom_w.h @@ -69,13 +69,13 @@ EndUserDocs */ void register_static_synapse_hom_w( const std::string& name ); template < typename targetidentifierT > -class static_synapse_hom_w : public Connection< targetidentifierT > +class static_synapse_hom_w : public Connection< targetidentifierT, TotalDelay > { public: // this line determines which common properties to use typedef CommonPropertiesHomW CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; // Explicitly declare all methods inherited from the dependent base // ConnectionBase. This avoids explicit name prefixes in all places these @@ -140,10 +140,10 @@ class static_synapse_hom_w : public Connection< targetidentifierT > void get_status( DictionaryDatum& d ) const; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } /** diff --git a/models/stdp_dopamine_synapse.h b/models/stdp_dopamine_synapse.h index 118c0054ff..83abb6f60f 100644 --- a/models/stdp_dopamine_synapse.h +++ b/models/stdp_dopamine_synapse.h @@ -193,12 +193,12 @@ STDPDopaCommonProperties::get_vt_node_id() const void register_stdp_dopamine_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_dopamine_synapse : public Connection< targetidentifierT > +class stdp_dopamine_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef STDPDopaCommonProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -221,7 +221,7 @@ class stdp_dopamine_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -285,7 +285,11 @@ class stdp_dopamine_synapse : public Connection< targetidentifierT > * \param receptor_type The ID of the requested receptor type */ void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& cp ) + check_connection( Node& s, + Node& t, + const size_t receptor_type, + const synindex syn_id, + const CommonPropertiesType& cp ) { if ( not cp.volume_transmitter_ ) { @@ -293,9 +297,9 @@ class stdp_dopamine_synapse : public Connection< targetidentifierT > } ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -529,7 +533,7 @@ stdp_dopamine_synapse< targetidentifierT >::send( Event& e, size_t t, const STDP Node* target = get_target( t ); // purely dendritic delay - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); double t_spike = e.get_stamp().get_ms(); @@ -588,7 +592,7 @@ stdp_dopamine_synapse< targetidentifierT >::trigger_update_weight( size_t t, // postsyn. neuron // purely dendritic delay - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t_last_update, t_trig] from postsyn. // neuron diff --git a/models/stdp_facetshw_synapse_hom.h b/models/stdp_facetshw_synapse_hom.h index 2b103eed48..4de8c8c926 100644 --- a/models/stdp_facetshw_synapse_hom.h +++ b/models/stdp_facetshw_synapse_hom.h @@ -235,12 +235,12 @@ class STDPFACETSHWHomCommonProperties : public CommonSynapseProperties * parameters are the same for all synapses. */ template < typename targetidentifierT > -class stdp_facetshw_synapse_hom : public Connection< targetidentifierT > +class stdp_facetshw_synapse_hom : public Connection< targetidentifierT, TotalDelay > { public: typedef STDPFACETSHWHomCommonProperties< targetidentifierT > CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -263,7 +263,7 @@ class stdp_facetshw_synapse_hom : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -312,13 +312,13 @@ class stdp_facetshw_synapse_hom : public Connection< targetidentifierT > * \param receptor_type The ID of the requested receptor type */ void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -498,7 +498,7 @@ stdp_facetshw_synapse_hom< targetidentifierT >::send( Event& e, // t_lastspike_ = 0 initially - double dendritic_delay = Time( Time::step( get_delay_steps() ) ).get_ms(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_nn_pre_centered_synapse.h b/models/stdp_nn_pre_centered_synapse.h index ec2791efbf..f08cae4a4f 100644 --- a/models/stdp_nn_pre_centered_synapse.h +++ b/models/stdp_nn_pre_centered_synapse.h @@ -130,12 +130,12 @@ EndUserDocs */ void register_stdp_nn_pre_centered_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_nn_pre_centered_synapse : public Connection< targetidentifierT > +class stdp_nn_pre_centered_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -159,7 +159,7 @@ class stdp_nn_pre_centered_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -195,13 +195,13 @@ class stdp_nn_pre_centered_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -257,7 +257,7 @@ stdp_nn_pre_centered_synapse< targetidentifierT >::send( Event& e, size_t t, con // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_nn_restr_synapse.h b/models/stdp_nn_restr_synapse.h index 7562266dc3..2b6f58c95b 100644 --- a/models/stdp_nn_restr_synapse.h +++ b/models/stdp_nn_restr_synapse.h @@ -125,12 +125,12 @@ EndUserDocs */ void register_stdp_nn_restr_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_nn_restr_synapse : public Connection< targetidentifierT > +class stdp_nn_restr_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -154,7 +154,7 @@ class stdp_nn_restr_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -191,13 +191,13 @@ class stdp_nn_restr_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -252,7 +252,7 @@ stdp_nn_restr_synapse< targetidentifierT >::send( Event& e, size_t t, const Comm // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_nn_symm_synapse.h b/models/stdp_nn_symm_synapse.h index 92970ec8ec..23f205cbd8 100644 --- a/models/stdp_nn_symm_synapse.h +++ b/models/stdp_nn_symm_synapse.h @@ -127,12 +127,12 @@ EndUserDocs */ void register_stdp_nn_symm_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_nn_symm_synapse : public Connection< targetidentifierT > +class stdp_nn_symm_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -156,7 +156,7 @@ class stdp_nn_symm_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -193,13 +193,13 @@ class stdp_nn_symm_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -254,7 +254,7 @@ stdp_nn_symm_synapse< targetidentifierT >::send( Event& e, size_t t, const Commo // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_pl_synapse_hom.h b/models/stdp_pl_synapse_hom.h index b01a79c79d..257ee6f6ae 100644 --- a/models/stdp_pl_synapse_hom.h +++ b/models/stdp_pl_synapse_hom.h @@ -42,8 +42,8 @@ Synapse type for spike-timing dependent plasticity with power law Description +++++++++++ -``stdp_pl_synapse`` is a connector to create synapses with spike time -dependent plasticity using homoegeneous parameters (as defined in [1]_). +``stdp_pl_synapse_hom`` is a connector to create synapses with spike time +dependent plasticity using homogeneous parameters (as defined in [1]_). Parameters ++++++++++ @@ -131,12 +131,12 @@ class STDPPLHomCommonProperties : public CommonSynapseProperties void register_stdp_pl_synapse_hom( const std::string& name ); template < typename targetidentifierT > -class stdp_pl_synapse_hom : public Connection< targetidentifierT > +class stdp_pl_synapse_hom : public Connection< targetidentifierT, TotalDelay > { public: typedef STDPPLHomCommonProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -159,7 +159,7 @@ class stdp_pl_synapse_hom : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -207,13 +207,13 @@ class stdp_pl_synapse_hom : public Connection< targetidentifierT > * \param receptor_type The ID of the requested receptor type */ void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -266,7 +266,7 @@ stdp_pl_synapse_hom< targetidentifierT >::send( Event& e, size_t t, const STDPPL Node* target = get_target( t ); - double dendritic_delay = get_delay(); + const double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; @@ -278,15 +278,17 @@ stdp_pl_synapse_hom< targetidentifierT >::send( Event& e, size_t t, const STDPPL while ( start != finish ) { minus_dt = t_lastspike_ - ( start->t_ + dendritic_delay ); - start++; // get_history() should make sure that // start->t_ > t_lastspike - dendritic_delay, i.e. minus_dt < 0 assert( minus_dt < -1.0 * kernel().connection_manager.get_stdp_eps() ); weight_ = facilitate_( weight_, Kplus_ * std::exp( minus_dt * cp.tau_plus_inv_ ), cp ); + + ++start; } // depression due to new pre-synaptic spike - weight_ = depress_( weight_, target->get_K_value( t_spike - dendritic_delay ), cp ); + const double K_minus = target->get_K_value( t_spike - dendritic_delay ); + weight_ = depress_( weight_, K_minus, cp ); e.set_receiver( *target ); e.set_weight( weight_ ); diff --git a/models/stdp_pl_synapse_hom_ax_delay.cpp b/models/stdp_pl_synapse_hom_ax_delay.cpp new file mode 100644 index 0000000000..cd20c81f2b --- /dev/null +++ b/models/stdp_pl_synapse_hom_ax_delay.cpp @@ -0,0 +1,88 @@ +/* + * stdp_pl_synapse_hom_ax_delay.cpp + * + * This file is part of NEST. + * + * Copyright (C) 2004 The NEST Initiative + * + * NEST is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * NEST is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NEST. If not, see . + * + */ + +#include "stdp_pl_synapse_hom_ax_delay.h" + +// Includes from nestkernel: +#include "common_synapse_properties.h" +#include "connector_model.h" +#include "event.h" +#include "nest_impl.h" + +// Includes from sli: +#include "dictdatum.h" + + +void +nest::register_stdp_pl_synapse_hom_ax_delay( const std::string& name ) +{ + register_connection_model< stdp_pl_synapse_hom_ax_delay >( name ); +} + +namespace nest +{ + +// +// Implementation of class STDPPLHomAxDelayCommonProperties. +// + +STDPPLHomAxDelayCommonProperties::STDPPLHomAxDelayCommonProperties() + : CommonSynapseProperties() + , tau_plus_( 20.0 ) + , tau_plus_inv_( 1. / tau_plus_ ) + , lambda_( 0.1 ) + , alpha_( 1.0 ) + , mu_( 0.4 ) +{ +} + +void +STDPPLHomAxDelayCommonProperties::get_status( DictionaryDatum& d ) const +{ + CommonSynapseProperties::get_status( d ); + + def< double >( d, names::tau_plus, tau_plus_ ); + def< double >( d, names::lambda, lambda_ ); + def< double >( d, names::alpha, alpha_ ); + def< double >( d, names::mu, mu_ ); +} + +void +STDPPLHomAxDelayCommonProperties::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + CommonSynapseProperties::set_status( d, cm ); + + updateValue< double >( d, names::tau_plus, tau_plus_ ); + if ( tau_plus_ > 0. ) + { + tau_plus_inv_ = 1. / tau_plus_; + } + else + { + throw BadProperty( "tau_plus > 0. required." ); + } + updateValue< double >( d, names::lambda, lambda_ ); + updateValue< double >( d, names::alpha, alpha_ ); + updateValue< double >( d, names::mu, mu_ ); +} + +} // of namespace nest diff --git a/models/stdp_pl_synapse_hom_ax_delay.h b/models/stdp_pl_synapse_hom_ax_delay.h new file mode 100644 index 0000000000..a7489446c4 --- /dev/null +++ b/models/stdp_pl_synapse_hom_ax_delay.h @@ -0,0 +1,431 @@ +/* + * stdp_pl_synapse_hom_ax_delay.h + * + * This file is part of NEST. + * + * Copyright (C) 2004 The NEST Initiative + * + * NEST is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * NEST is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NEST. If not, see . + * + */ + +#ifndef STDP_PL_SYNAPSE_HOM_AX_DELAY_H +#define STDP_PL_SYNAPSE_HOM_AX_DELAY_H + +// C++ includes: +#include + +// Includes from nestkernel: +#include "archiving_node.h" +#include "connection.h" + +namespace nest +{ + +/* BeginUserDocs: synapse, spike-timing-dependent plasticity + +Short description ++++++++++++++++++ + +Synapse type for spike-timing dependent plasticity with power law and both dendritic and axonal delays + +Description ++++++++++++ + +``stdp_pl_synapse_hom_ax_delay`` is a connector to create synapses with spike time dependent plasticity using + homogeneous parameters (as defined in [1]_). Both axonal and dendritic delays can be specified for this model. + +Parameters +++++++++++ + +========= ====== ==================================================== + tau_plus ms Time constant of STDP window, potentiation + (tau_minus defined in postsynaptic neuron) + lambda real Learning rate + alpha real Asymmetry parameter (scales depressing increments as + alpha*lambda) + mu real Weight dependence exponent, potentiation +========= ====== ==================================================== + +The parameters can only be set by SetDefaults and apply to all synapses of +the model. + +.. warning:: + + This synaptic plasticity rule does not take + :ref:`precise spike timing ` into + account. When calculating the weight update, the precise spike time part + of the timestamp is ignored. + +References +++++++++++ + +.. [1] Morrison A, Aertsen A, Diesmann M. (2007) Spike-timing dependent + plasticity in balanced random netrks. Neural Computation, + 19(6):1437-1467. DOI: https://doi.org/10.1162/neco.2007.19.6.1437 + +Transmits ++++++++++ + +SpikeEvent + +See also +++++++++ + +stdp_synapse, tsodyks_synapse, static_synapse + +EndUserDocs */ + +/** + * Class containing the common properties for all synapses of type + * stdp_pl_synapse_hom_ax_delay. + */ +class STDPPLHomAxDelayCommonProperties : public CommonSynapseProperties +{ + +public: + /** + * Default constructor. + * Sets all property values to defaults. + */ + STDPPLHomAxDelayCommonProperties(); + + /** + * Get all properties and put them into a dictionary. + */ + void get_status( DictionaryDatum& d ) const; + + /** + * Set properties from the values given in dictionary. + */ + void set_status( const DictionaryDatum& d, ConnectorModel& cm ); + + // data members common to all connections + double tau_plus_; + double tau_plus_inv_; //!< 1 / tau_plus for efficiency + double lambda_; + double alpha_; + double mu_; +}; + +/** + * Class representing an STDP connection with homogeneous parameters, i.e. parameters are the same for all synapses. + */ +void register_stdp_pl_synapse_hom_ax_delay( const std::string& name ); + +/** + * Class representing an STDP connection with homogeneous parameters, i.e. + * parameters are the same for all synapses. + */ +template < typename targetidentifierT > +class stdp_pl_synapse_hom_ax_delay : public Connection< targetidentifierT, AxonalDendriticDelay > +{ + +public: + typedef STDPPLHomAxDelayCommonProperties CommonPropertiesType; + typedef Connection< targetidentifierT, AxonalDendriticDelay > ConnectionBase; + + static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY + | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC + | ConnectionModelProperties::SUPPORTS_LBL; + + /** + * Default Constructor. + * Sets default values for all parameters. Needed by GenericConnectorModel. + */ + stdp_pl_synapse_hom_ax_delay(); + + /** + * Copy constructor from a property object. + * Needs to be defined properly in order for GenericConnector to work. + */ + stdp_pl_synapse_hom_ax_delay( const stdp_pl_synapse_hom_ax_delay& ) = default; + stdp_pl_synapse_hom_ax_delay& operator=( const stdp_pl_synapse_hom_ax_delay& ) = default; + + // Explicitly declare all methods inherited from the dependent base + // ConnectionBase. This avoids explicit name prefixes in all places these + // functions are used. Since ConnectionBase depends on the template parameter, + // they are not automatically found in the base class. + using ConnectionBase::get_axonal_delay_ms; + using ConnectionBase::get_axonal_delay_steps; + using ConnectionBase::get_delay_steps; + using ConnectionBase::get_dendritic_delay_ms; + using ConnectionBase::get_dendritic_delay_steps; + using ConnectionBase::get_rport; + using ConnectionBase::get_target; + + /** + * Get all properties of this connection and put them into a dictionary. + */ + void get_status( DictionaryDatum& d ) const; + + /** + * Set properties of this connection from the values given in dictionary. + */ + void set_status( const DictionaryDatum& d, ConnectorModel& cm ); + + /** + * Send an event to the receiver of this connection. + * \param e The event to send + */ + bool send( Event& e, size_t t, const STDPPLHomAxDelayCommonProperties& ); + + /** + * Framework for STDP with predominantly axonal delays: + * Correct this synapse and the corresponding previously sent spike + * taking into account a new post-synaptic spike. + */ + void correct_synapse_stdp_ax_delay( const size_t tid, + const double t_last_spike, + double& weight_revert, + const double t_post_spike, + const STDPPLHomAxDelayCommonProperties& cp ); + + class ConnTestDummyNode : public ConnTestDummyNodeBase + { + public: + // Ensure proper overriding of overloaded virtual functions. + // Return values from functions are ignored. + using ConnTestDummyNodeBase::handles_test_event; + size_t + handles_test_event( SpikeEvent&, size_t ) override + { + return invalid_port; + } + }; + + /* + * This function calls check_connection on the sender and checks if the + * receiver accepts the event type and receptor type requested by the sender. + * Node::check_connection() will either confirm the receiver port by returning + * true or false if the connection should be ignored. + * We have to override the base class' implementation, since for STDP + * connections we have to call register_stdp_pl_connection on the target + * neuron to inform the Archiver to collect spikes for this connection. + * + * \param s The source node + * \param r The target node + * \param receptor_type The ID of the requested receptor type + */ + void + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) + { + if ( kernel().sp_manager.is_structural_plasticity_enabled() ) + { + throw IllegalConnection( "Structural plasticity is not supported in combination with axonal delays." ); + } + + ConnTestDummyNode dummy_target; + + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); + + if ( get_axonal_delay_ms() + get_dendritic_delay_ms() < kernel().connection_manager.get_stdp_eps() ) + { + throw BadProperty( "Combination of axonal and dendritic delay has to be more than 0." ); + } + t.register_stdp_connection( t_lastspike_ - get_dendritic_delay_ms() + get_axonal_delay_ms(), + get_dendritic_delay_ms(), + get_axonal_delay_ms() ); + + if ( get_axonal_delay_ms() >= get_dendritic_delay_ms() ) + { + CorrectionSpikeEvent e; + t.handles_test_event( e, receptor_type ); + } + } + + void + set_weight( double w ) + { + weight_ = w; + } + +private: + double + facilitate_( double w, double kplus, const STDPPLHomAxDelayCommonProperties& cp ) + { + return w + ( cp.lambda_ * std::pow( w, cp.mu_ ) * kplus ); + } + + double + depress_( double w, double kminus, const STDPPLHomAxDelayCommonProperties& cp ) + { + double new_w = w - ( cp.lambda_ * cp.alpha_ * w * kminus ); + return new_w > 0.0 ? new_w : 0.0; + } + + // data members of each connection + double weight_; + double Kplus_; + double t_lastspike_; +}; + +template < typename targetidentifierT > +constexpr ConnectionModelProperties stdp_pl_synapse_hom_ax_delay< targetidentifierT >::properties; + +/** + * Send an event to the receiver of this connection. + * \param e The event to send + * \param p The port under which this connection is stored in the Connector. + */ +template < typename targetidentifierT > +inline bool +stdp_pl_synapse_hom_ax_delay< targetidentifierT >::send( Event& e, + size_t tid, + const STDPPLHomAxDelayCommonProperties& cp ) +{ + // synapse STDP depressing/facilitation dynamics + const double axonal_delay_ms = get_axonal_delay_ms(); + const double dendritic_delay_ms = get_dendritic_delay_ms(); + const double t_spike = e.get_stamp().get_ms(); + + // t_lastspike_ = 0 initially + Node* target = get_target( tid ); + + // get spike history in relevant range (t1, t2] from postsynaptic neuron + std::deque< histentry >::iterator start; + std::deque< histentry >::iterator finish; + target->get_history( t_lastspike_ - dendritic_delay_ms + axonal_delay_ms, + t_spike - dendritic_delay_ms + axonal_delay_ms, + &start, + &finish ); + + // facilitation due to postsynaptic spikes since last pre-synaptic spike + double minus_dt; + while ( start != finish ) + { + minus_dt = t_lastspike_ + axonal_delay_ms - ( start->t_ + dendritic_delay_ms ); + // get_history() should make sure that + // start->t_ > t_lastspike - dendritic_delay, i.e. minus_dt < 0 + assert( minus_dt < -1.0 * kernel().connection_manager.get_stdp_eps() ); + weight_ = facilitate_( weight_, Kplus_ * std::exp( minus_dt * cp.tau_plus_inv_ ), cp ); + ++start; + } + + // Framework for STDP with predominantly axonal delays: + // Store weight before depression for potential later correction + const double weight_revert = weight_; + + // depression due to new pre-synaptic spike + const double K_minus = target->get_K_value( t_spike + axonal_delay_ms - dendritic_delay_ms ); + weight_ = depress_( weight_, K_minus, cp ); + + e.set_receiver( *target ); + e.set_weight( weight_ ); + e.set_delay_steps( get_delay_steps() ); + e.set_rport( get_rport() ); + e(); + + // axonal_delay-dendritic_delay = total_delay-2*dendritic_delay + const long time_while_critical = + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ) - 2 * get_dendritic_delay_steps() + 1; + // Only add correction entry if there could potentially be any post-synaptic spike that occurs before the + // pre-synaptic one arrives at the synapse. Has to be strictly greater than min_delay, because a post-synaptic spike + // at time slice_origin+min_delay corresponds to the last update step in the current slice (before delivery) and was + // thus already known at time of delivery of the pre-synaptic one. + if ( time_while_critical > 0 ) + { + static_cast< ArchivingNode* >( target )->add_correction_entry_stdp_ax_delay( + static_cast< SpikeEvent& >( e ), t_lastspike_, weight_revert, time_while_critical ); + } + + Kplus_ = Kplus_ * std::exp( ( t_lastspike_ - t_spike ) * cp.tau_plus_inv_ ) + 1.0; + + t_lastspike_ = t_spike; + + return true; +} + +template < typename targetidentifierT > +stdp_pl_synapse_hom_ax_delay< targetidentifierT >::stdp_pl_synapse_hom_ax_delay() + : ConnectionBase() + , weight_( 1.0 ) + , Kplus_( 0.0 ) + , t_lastspike_( 0.0 ) +{ +} + +template < typename targetidentifierT > +void +stdp_pl_synapse_hom_ax_delay< targetidentifierT >::get_status( DictionaryDatum& d ) const +{ + + // base class properties, different for individual synapse + ConnectionBase::get_status( d ); + def< double >( d, names::weight, weight_ ); + + // own properties, different for individual synapse + def< double >( d, names::Kplus, Kplus_ ); + def< long >( d, names::size_of, sizeof( *this ) ); +} + +template < typename targetidentifierT > +void +stdp_pl_synapse_hom_ax_delay< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + ConnectionBase::set_status( d, cm ); + updateValue< double >( d, names::weight, weight_ ); + + updateValue< double >( d, names::Kplus, Kplus_ ); +} + +template < typename targetidentifierT > +inline void +stdp_pl_synapse_hom_ax_delay< targetidentifierT >::correct_synapse_stdp_ax_delay( const size_t tid, + const double t_last_spike, + double& weight_revert, + const double t_post_spike, + const STDPPLHomAxDelayCommonProperties& cp ) +{ + const double t_spike = t_lastspike_; // no new pre-synaptic spike since last send() + const double wrong_weight = weight_; // incorrectly transmitted weight + weight_ = weight_revert; // removes the last depressive step + Node* target = get_target( tid ); + + const double axonal_delay_ms = get_axonal_delay_ms(); + double dendritic_delay_ms = get_dendritic_delay_ms(); + + // facilitation due to new post-synaptic spike + const double minus_dt = t_last_spike + axonal_delay_ms - ( t_post_spike + dendritic_delay_ms ); + + double K_plus_revert; + // Only facilitate if not facilitated already (only if first correction for this post-spike) + if ( minus_dt < -1.0 * kernel().connection_manager.get_stdp_eps() ) + { + // Kplus value at t_last_spike_ needed + K_plus_revert = ( Kplus_ - 1.0 ) / std::exp( ( t_last_spike - t_spike ) * cp.tau_plus_inv_ ); + weight_ = facilitate_( weight_, K_plus_revert * std::exp( minus_dt * cp.tau_plus_inv_ ), cp ); + + // update weight_revert in case further correction will be required later + weight_revert = weight_; + } + + // depression taking into account new post-synaptic spike + const double K_minus = target->get_K_value( t_spike + axonal_delay_ms - dendritic_delay_ms ); + weight_ = depress_( weight_, K_minus, cp ); + + // send a correcting event to the target neuron + CorrectionSpikeEvent e; + e.set_receiver( *target ); + e.set_weight( wrong_weight ); + e.set_new_weight( weight_ ); + e.set_delay_steps( get_delay_steps() ); + e.set_rport( get_rport() ); + e.set_stamp( Time::ms_stamp( t_spike ) ); + e(); +} + +} // of namespace nest + +#endif // of #ifndef STDP_PL_SYNAPSE_HOM_AX_DELAY_H diff --git a/models/stdp_synapse.h b/models/stdp_synapse.h index 61b3cbcafa..771a88dfbf 100644 --- a/models/stdp_synapse.h +++ b/models/stdp_synapse.h @@ -117,12 +117,12 @@ EndUserDocs */ void register_stdp_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_synapse : public Connection< targetidentifierT > +class stdp_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -146,7 +146,7 @@ class stdp_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -183,13 +183,13 @@ class stdp_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -245,7 +245,7 @@ stdp_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonSynapse // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_synapse_hom.h b/models/stdp_synapse_hom.h index 803f513585..a8b8c9689f 100644 --- a/models/stdp_synapse_hom.h +++ b/models/stdp_synapse_hom.h @@ -157,12 +157,12 @@ class STDPHomCommonProperties : public CommonSynapseProperties void register_stdp_synapse_hom( const std::string& name ); template < typename targetidentifierT > -class stdp_synapse_hom : public Connection< targetidentifierT > +class stdp_synapse_hom : public Connection< targetidentifierT, TotalDelay > { public: typedef STDPHomCommonProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -186,7 +186,7 @@ class stdp_synapse_hom : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -241,12 +241,12 @@ class stdp_synapse_hom : public Connection< targetidentifierT > * \param receptor_type The ID of the requested receptor type */ void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } private: @@ -302,7 +302,7 @@ stdp_synapse_hom< targetidentifierT >::send( Event& e, size_t t, const STDPHomCo // t_lastspike_ = 0 initially Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/stdp_triplet_synapse.h b/models/stdp_triplet_synapse.h index f2a8f8ced3..ec8d265925 100644 --- a/models/stdp_triplet_synapse.h +++ b/models/stdp_triplet_synapse.h @@ -122,12 +122,12 @@ EndUserDocs */ void register_stdp_triplet_synapse( const std::string& name ); template < typename targetidentifierT > -class stdp_triplet_synapse : public Connection< targetidentifierT > +class stdp_triplet_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -157,7 +157,7 @@ class stdp_triplet_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places // these functions are used. Since ConnectionBase depends on the template // parameter, they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -206,13 +206,13 @@ class stdp_triplet_synapse : public Connection< targetidentifierT > * \param receptor_type The ID of the requested receptor type */ void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -264,7 +264,7 @@ inline bool stdp_triplet_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonSynapseProperties& ) { double t_spike = e.get_stamp().get_ms(); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); Node* target = get_target( t ); // get spike history in relevant range (t1, t2] from postsynaptic neuron diff --git a/models/step_current_generator.cpp b/models/step_current_generator.cpp index d006dc30af..24f03f4303 100644 --- a/models/step_current_generator.cpp +++ b/models/step_current_generator.cpp @@ -49,28 +49,27 @@ RecordablesMap< step_current_generator >::create() { insert_( Name( names::I ), &step_current_generator::get_I_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::step_current_generator::Parameters_::Parameters_() +step_current_generator::Parameters_::Parameters_() : amp_time_stamps_() , amp_values_() // pA , allow_offgrid_amp_times_( false ) { } -nest::step_current_generator::Parameters_::Parameters_( const Parameters_& p ) +step_current_generator::Parameters_::Parameters_( const Parameters_& p ) : amp_time_stamps_( p.amp_time_stamps_ ) , amp_values_( p.amp_values_ ) , allow_offgrid_amp_times_( p.allow_offgrid_amp_times_ ) { } -nest::step_current_generator::Parameters_& -nest::step_current_generator::Parameters_::operator=( const Parameters_& p ) +step_current_generator::Parameters_& +step_current_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -84,19 +83,19 @@ nest::step_current_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::step_current_generator::State_::State_() +step_current_generator::State_::State_() : I_( 0.0 ) // pA { } -nest::step_current_generator::Buffers_::Buffers_( step_current_generator& n ) +step_current_generator::Buffers_::Buffers_( step_current_generator& n ) : idx_( 0 ) , amp_( 0 ) , logger_( n ) { } -nest::step_current_generator::Buffers_::Buffers_( const Buffers_&, step_current_generator& n ) +step_current_generator::Buffers_::Buffers_( const Buffers_&, step_current_generator& n ) : idx_( 0 ) , amp_( 0 ) , logger_( n ) @@ -108,7 +107,7 @@ nest::step_current_generator::Buffers_::Buffers_( const Buffers_&, step_current_ * ---------------------------------------------------------------- */ void -nest::step_current_generator::Parameters_::get( DictionaryDatum& d ) const +step_current_generator::Parameters_::get( DictionaryDatum& d ) const { std::vector< double >* times_ms = new std::vector< double >(); times_ms->reserve( amp_time_stamps_.size() ); @@ -121,8 +120,8 @@ nest::step_current_generator::Parameters_::get( DictionaryDatum& d ) const ( *d )[ names::allow_offgrid_times ] = BoolDatum( allow_offgrid_amp_times_ ); } -nest::Time -nest::step_current_generator::Parameters_::validate_time_( double t, const Time& t_previous ) +Time +step_current_generator::Parameters_::validate_time_( double t, const Time& t_previous ) { if ( t <= 0.0 ) { @@ -166,7 +165,7 @@ nest::step_current_generator::Parameters_::validate_time_( double t, const Time& } void -nest::step_current_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) +step_current_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) { std::vector< double > new_times; const bool times_changed = updateValue< std::vector< double > >( d, names::amplitude_times, new_times ); @@ -226,7 +225,7 @@ nest::step_current_generator::Parameters_::set( const DictionaryDatum& d, Buffer * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::step_current_generator::step_current_generator() +step_current_generator::step_current_generator() : StimulationDevice() , P_() , S_() @@ -235,7 +234,7 @@ nest::step_current_generator::step_current_generator() recordablesMap_.create(); } -nest::step_current_generator::step_current_generator( const step_current_generator& n ) +step_current_generator::step_current_generator( const step_current_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -249,13 +248,13 @@ nest::step_current_generator::step_current_generator( const step_current_generat * ---------------------------------------------------------------- */ void -nest::step_current_generator::init_state_() +step_current_generator::init_state_() { StimulationDevice::init_state(); } void -nest::step_current_generator::init_buffers_() +step_current_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); @@ -265,7 +264,7 @@ nest::step_current_generator::init_buffers_() } void -nest::step_current_generator::pre_run_hook() +step_current_generator::pre_run_hook() { B_.logger_.init(); StimulationDevice::pre_run_hook(); @@ -277,7 +276,7 @@ nest::step_current_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::step_current_generator::update( Time const& origin, const long from, const long to ) +step_current_generator::update( Time const& origin, const long from, const long to ) { assert( P_.amp_time_stamps_.size() == P_.amp_values_.size() ); @@ -319,7 +318,7 @@ nest::step_current_generator::update( Time const& origin, const long from, const } void -nest::step_current_generator::handle( DataLoggingRequest& e ) +step_current_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -328,7 +327,7 @@ nest::step_current_generator::handle( DataLoggingRequest& e ) * Other functions * ---------------------------------------------------------------- */ void -nest::step_current_generator::set_data_from_stimulation_backend( std::vector< double >& time_amplitude ) +step_current_generator::set_data_from_stimulation_backend( std::vector< double >& time_amplitude ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -367,3 +366,5 @@ nest::step_current_generator::set_data_from_stimulation_backend( std::vector< do // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/step_rate_generator.cpp b/models/step_rate_generator.cpp index dfe104987d..379df77866 100644 --- a/models/step_rate_generator.cpp +++ b/models/step_rate_generator.cpp @@ -49,28 +49,27 @@ RecordablesMap< step_rate_generator >::create() { insert_( Name( names::rate ), &step_rate_generator::get_rate_ ); } -} /* ---------------------------------------------------------------- * Default constructors defining default parameter * ---------------------------------------------------------------- */ -nest::step_rate_generator::Parameters_::Parameters_() +step_rate_generator::Parameters_::Parameters_() : amp_time_stamps_() , amp_values_() // pA , allow_offgrid_amp_times_( false ) { } -nest::step_rate_generator::Parameters_::Parameters_( const Parameters_& p ) +step_rate_generator::Parameters_::Parameters_( const Parameters_& p ) : amp_time_stamps_( p.amp_time_stamps_ ) , amp_values_( p.amp_values_ ) , allow_offgrid_amp_times_( p.allow_offgrid_amp_times_ ) { } -nest::step_rate_generator::Parameters_& -nest::step_rate_generator::Parameters_::operator=( const Parameters_& p ) +step_rate_generator::Parameters_& +step_rate_generator::Parameters_::operator=( const Parameters_& p ) { if ( this == &p ) { @@ -84,19 +83,19 @@ nest::step_rate_generator::Parameters_::operator=( const Parameters_& p ) return *this; } -nest::step_rate_generator::State_::State_() +step_rate_generator::State_::State_() : rate_( 0.0 ) { } -nest::step_rate_generator::Buffers_::Buffers_( step_rate_generator& n ) +step_rate_generator::Buffers_::Buffers_( step_rate_generator& n ) : idx_( 0 ) , amp_( 0 ) , logger_( n ) { } -nest::step_rate_generator::Buffers_::Buffers_( const Buffers_&, step_rate_generator& n ) +step_rate_generator::Buffers_::Buffers_( const Buffers_&, step_rate_generator& n ) : idx_( 0 ) , amp_( 0 ) , logger_( n ) @@ -108,7 +107,7 @@ nest::step_rate_generator::Buffers_::Buffers_( const Buffers_&, step_rate_genera * ---------------------------------------------------------------- */ void -nest::step_rate_generator::Parameters_::get( DictionaryDatum& d ) const +step_rate_generator::Parameters_::get( DictionaryDatum& d ) const { std::vector< double >* times_ms = new std::vector< double >(); times_ms->reserve( amp_time_stamps_.size() ); @@ -121,8 +120,8 @@ nest::step_rate_generator::Parameters_::get( DictionaryDatum& d ) const ( *d )[ names::allow_offgrid_times ] = BoolDatum( allow_offgrid_amp_times_ ); } -nest::Time -nest::step_rate_generator::Parameters_::validate_time_( double t, const Time& t_previous ) +Time +step_rate_generator::Parameters_::validate_time_( double t, const Time& t_previous ) { if ( t <= 0.0 ) { @@ -166,7 +165,7 @@ nest::step_rate_generator::Parameters_::validate_time_( double t, const Time& t_ } void -nest::step_rate_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) +step_rate_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& b, Node* ) { std::vector< double > new_times; const bool times_changed = updateValue< std::vector< double > >( d, names::amplitude_times, new_times ); @@ -226,7 +225,7 @@ nest::step_rate_generator::Parameters_::set( const DictionaryDatum& d, Buffers_& * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::step_rate_generator::step_rate_generator() +step_rate_generator::step_rate_generator() : StimulationDevice() , P_() , S_() @@ -235,7 +234,7 @@ nest::step_rate_generator::step_rate_generator() recordablesMap_.create(); } -nest::step_rate_generator::step_rate_generator( const step_rate_generator& n ) +step_rate_generator::step_rate_generator( const step_rate_generator& n ) : StimulationDevice( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -249,13 +248,13 @@ nest::step_rate_generator::step_rate_generator( const step_rate_generator& n ) * ---------------------------------------------------------------- */ void -nest::step_rate_generator::init_state_() +step_rate_generator::init_state_() { StimulationDevice::init_state(); } void -nest::step_rate_generator::init_buffers_() +step_rate_generator::init_buffers_() { StimulationDevice::init_buffers(); B_.logger_.reset(); @@ -265,7 +264,7 @@ nest::step_rate_generator::init_buffers_() } void -nest::step_rate_generator::pre_run_hook() +step_rate_generator::pre_run_hook() { B_.logger_.init(); @@ -278,7 +277,7 @@ nest::step_rate_generator::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::step_rate_generator::update( Time const& origin, const long from, const long to ) +step_rate_generator::update( Time const& origin, const long from, const long to ) { assert( P_.amp_time_stamps_.size() == P_.amp_values_.size() ); @@ -332,7 +331,7 @@ nest::step_rate_generator::update( Time const& origin, const long from, const lo } void -nest::step_rate_generator::handle( DataLoggingRequest& e ) +step_rate_generator::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); } @@ -341,7 +340,7 @@ nest::step_rate_generator::handle( DataLoggingRequest& e ) * Other functions * ---------------------------------------------------------------- */ void -nest::step_rate_generator::set_data_from_stimulation_backend( std::vector< double >& time_amplitude ) +step_rate_generator::set_data_from_stimulation_backend( std::vector< double >& time_amplitude ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -380,3 +379,5 @@ nest::step_rate_generator::set_data_from_stimulation_backend( std::vector< doubl // if we get here, temporary contains consistent set of properties P_ = ptmp; } + +} // namespace nest \ No newline at end of file diff --git a/models/tanh_rate.cpp b/models/tanh_rate.cpp index c1a41cb679..911da5cf24 100644 --- a/models/tanh_rate.cpp +++ b/models/tanh_rate.cpp @@ -68,29 +68,29 @@ nonlinearities_tanh_rate::set( const DictionaryDatum& d, Node* node ) */ template <> void -RecordablesMap< nest::tanh_rate_ipn >::create() +RecordablesMap< tanh_rate_ipn >::create() { // use standard names wherever you can for consistency! - insert_( names::rate, &nest::tanh_rate_ipn::get_rate_ ); - insert_( names::noise, &nest::tanh_rate_ipn::get_noise_ ); + insert_( names::rate, &tanh_rate_ipn::get_rate_ ); + insert_( names::noise, &tanh_rate_ipn::get_noise_ ); } template <> void -RecordablesMap< nest::tanh_rate_opn >::create() +RecordablesMap< tanh_rate_opn >::create() { // use standard names wherever you can for consistency! - insert_( names::rate, &nest::tanh_rate_opn::get_rate_ ); - insert_( names::noise, &nest::tanh_rate_opn::get_noise_ ); - insert_( names::noisy_rate, &nest::tanh_rate_opn::get_noisy_rate_ ); + insert_( names::rate, &tanh_rate_opn::get_rate_ ); + insert_( names::noise, &tanh_rate_opn::get_noise_ ); + insert_( names::noisy_rate, &tanh_rate_opn::get_noisy_rate_ ); } template <> void -RecordablesMap< nest::rate_transformer_tanh >::create() +RecordablesMap< rate_transformer_tanh >::create() { // use standard names wherever you can for consistency! - insert_( names::rate, &nest::rate_transformer_tanh::get_rate_ ); + insert_( names::rate, &rate_transformer_tanh::get_rate_ ); } } // namespace nest diff --git a/models/tsodyks2_synapse.h b/models/tsodyks2_synapse.h index a57f300244..cf64aea9a6 100644 --- a/models/tsodyks2_synapse.h +++ b/models/tsodyks2_synapse.h @@ -119,11 +119,11 @@ EndUserDocs */ void register_tsodyks2_synapse( const std::string& name ); template < typename targetidentifierT > -class tsodyks2_synapse : public Connection< targetidentifierT > +class tsodyks2_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -153,7 +153,7 @@ class tsodyks2_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -190,10 +190,10 @@ class tsodyks2_synapse : public Connection< targetidentifierT > void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } void diff --git a/models/tsodyks_synapse.h b/models/tsodyks_synapse.h index bb6c1e3938..3dfb0bab31 100644 --- a/models/tsodyks_synapse.h +++ b/models/tsodyks_synapse.h @@ -139,11 +139,11 @@ EndUserDocs */ void register_tsodyks_synapse( const std::string& name ); template < typename targetidentifierT > -class tsodyks_synapse : public Connection< targetidentifierT > +class tsodyks_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -173,7 +173,7 @@ class tsodyks_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -209,10 +209,10 @@ class tsodyks_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } void diff --git a/models/tsodyks_synapse_hom.h b/models/tsodyks_synapse_hom.h index e01c49f04b..b97c9fc4e9 100644 --- a/models/tsodyks_synapse_hom.h +++ b/models/tsodyks_synapse_hom.h @@ -173,11 +173,11 @@ class TsodyksHomCommonProperties : public CommonPropertiesHomW void register_tsodyks_synapse_hom( const std::string& name ); template < typename targetidentifierT > -class tsodyks_synapse_hom : public Connection< targetidentifierT > +class tsodyks_synapse_hom : public Connection< targetidentifierT, TotalDelay > { public: typedef TsodyksHomCommonProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -242,10 +242,10 @@ class tsodyks_synapse_hom : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); } void diff --git a/models/urbanczik_synapse.h b/models/urbanczik_synapse.h index 04fcd05d06..3ef6f72a0f 100644 --- a/models/urbanczik_synapse.h +++ b/models/urbanczik_synapse.h @@ -111,12 +111,12 @@ EndUserDocs */ void register_urbanczik_synapse( const std::string& name ); template < typename targetidentifierT > -class urbanczik_synapse : public Connection< targetidentifierT > +class urbanczik_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::REQUIRES_URBANCZIK_ARCHIVING @@ -141,7 +141,7 @@ class urbanczik_synapse : public Connection< targetidentifierT > // ConnectionBase. This avoids explicit name prefixes in all places these // functions are used. Since ConnectionBase depends on the template parameter, // they are not automatically found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -178,13 +178,13 @@ class urbanczik_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -225,7 +225,7 @@ urbanczik_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonSy double t_spike = e.get_stamp().get_ms(); // use accessor functions (inherited from Connection< >) to obtain delay and target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry_extended >::iterator start; diff --git a/models/vogels_sprekeler_synapse.h b/models/vogels_sprekeler_synapse.h index cf30380486..f7ddd4ddb5 100644 --- a/models/vogels_sprekeler_synapse.h +++ b/models/vogels_sprekeler_synapse.h @@ -92,12 +92,12 @@ EndUserDocs */ void register_vogels_sprekeler_synapse( const std::string& name ); template < typename targetidentifierT > -class vogels_sprekeler_synapse : public Connection< targetidentifierT > +class vogels_sprekeler_synapse : public Connection< targetidentifierT, TotalDelay > { public: typedef CommonSynapseProperties CommonPropertiesType; - typedef Connection< targetidentifierT > ConnectionBase; + typedef Connection< targetidentifierT, TotalDelay > ConnectionBase; static constexpr ConnectionModelProperties properties = ConnectionModelProperties::HAS_DELAY | ConnectionModelProperties::IS_PRIMARY | ConnectionModelProperties::SUPPORTS_HPC @@ -123,7 +123,7 @@ class vogels_sprekeler_synapse : public Connection< targetidentifierT > // Since ConnectionBase depends on the template parameter, they are not // automatically // found in the base class. - using ConnectionBase::get_delay; + using ConnectionBase::get_delay_ms; using ConnectionBase::get_delay_steps; using ConnectionBase::get_rport; using ConnectionBase::get_target; @@ -161,13 +161,13 @@ class vogels_sprekeler_synapse : public Connection< targetidentifierT > }; void - check_connection( Node& s, Node& t, size_t receptor_type, const CommonPropertiesType& ) + check_connection( Node& s, Node& t, const size_t receptor_type, const synindex syn_id, const CommonPropertiesType& ) { ConnTestDummyNode dummy_target; - ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); + ConnectionBase::check_connection_( dummy_target, s, t, syn_id, receptor_type ); - t.register_stdp_connection( t_lastspike_ - get_delay(), get_delay() ); + t.register_stdp_connection( t_lastspike_ - get_delay_ms(), get_delay_ms(), 0 ); } void @@ -223,7 +223,7 @@ vogels_sprekeler_synapse< targetidentifierT >::send( Event& e, size_t t, const C // use accessor functions (inherited from Connection< >) to obtain delay and // target Node* target = get_target( t ); - double dendritic_delay = get_delay(); + double dendritic_delay = get_delay_ms(); // get spike history in relevant range (t1, t2] from postsynaptic neuron std::deque< histentry >::iterator start; diff --git a/models/volume_transmitter.cpp b/models/volume_transmitter.cpp index 659838b288..aa390aa45f 100644 --- a/models/volume_transmitter.cpp +++ b/models/volume_transmitter.cpp @@ -37,18 +37,20 @@ // Includes from sli: #include "dictutils.h" +namespace nest +{ + void -nest::register_volume_transmitter( const std::string& name ) +register_volume_transmitter( const std::string& name ) { register_node_model< volume_transmitter >( name ); } - /* ---------------------------------------------------------------- * Default constructor defining default parameters * ---------------------------------------------------------------- */ -nest::volume_transmitter::Parameters_::Parameters_() +volume_transmitter::Parameters_::Parameters_() : deliver_interval_( 1 ) // in steps of mindelay { } @@ -58,12 +60,13 @@ nest::volume_transmitter::Parameters_::Parameters_() * ---------------------------------------------------------------- */ void -nest::volume_transmitter::Parameters_::get( DictionaryDatum& d ) const +volume_transmitter::Parameters_::get( DictionaryDatum& d ) const { def< long >( d, names::deliver_interval, deliver_interval_ ); } -void ::nest::volume_transmitter::Parameters_::set( const DictionaryDatum& d, Node* node ) +void +volume_transmitter::Parameters_::set( const DictionaryDatum& d, Node* node ) { updateValueParam< long >( d, names::deliver_interval, deliver_interval_, node ); } @@ -72,14 +75,14 @@ void ::nest::volume_transmitter::Parameters_::set( const DictionaryDatum& d, Nod * Default and copy constructor for volume transmitter * ---------------------------------------------------------------- */ -nest::volume_transmitter::volume_transmitter() +volume_transmitter::volume_transmitter() : Node() , P_() , local_device_id_( 0 ) { } -nest::volume_transmitter::volume_transmitter( const volume_transmitter& n ) +volume_transmitter::volume_transmitter( const volume_transmitter& n ) : Node( n ) , P_( n.P_ ) , local_device_id_( n.local_device_id_ ) @@ -87,7 +90,7 @@ nest::volume_transmitter::volume_transmitter( const volume_transmitter& n ) } void -nest::volume_transmitter::init_buffers_() +volume_transmitter::init_buffers_() { B_.neuromodulatory_spikes_.clear(); B_.spikecounter_.clear(); @@ -95,14 +98,14 @@ nest::volume_transmitter::init_buffers_() } void -nest::volume_transmitter::pre_run_hook() +volume_transmitter::pre_run_hook() { // +1 as pseudo dopa spike at t_trig is inserted after trigger_update_weight B_.spikecounter_.reserve( kernel().connection_manager.get_min_delay() * P_.deliver_interval_ + 1 ); } void -nest::volume_transmitter::update( const Time&, const long from, const long to ) +volume_transmitter::update( const Time&, const long from, const long to ) { // spikes that arrive in this time slice are stored in spikecounter_ double t_spike; @@ -139,8 +142,10 @@ nest::volume_transmitter::update( const Time&, const long from, const long to ) } void -nest::volume_transmitter::handle( SpikeEvent& e ) +volume_transmitter::handle( SpikeEvent& e ) { B_.neuromodulatory_spikes_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), static_cast< double >( e.get_multiplicity() ) ); } + +} \ No newline at end of file diff --git a/models/weight_recorder.cpp b/models/weight_recorder.cpp index 33f1fef67d..234fc469fe 100644 --- a/models/weight_recorder.cpp +++ b/models/weight_recorder.cpp @@ -39,34 +39,36 @@ #include "dict.h" #include "dictutils.h" +namespace nest +{ + void -nest::register_weight_recorder( const std::string& name ) +register_weight_recorder( const std::string& name ) { register_node_model< weight_recorder >( name ); } - // record time, node ID, weight and receiver node ID -nest::weight_recorder::weight_recorder() +weight_recorder::weight_recorder() : RecordingDevice() , P_() { } -nest::weight_recorder::weight_recorder( const weight_recorder& n ) +weight_recorder::weight_recorder( const weight_recorder& n ) : RecordingDevice( n ) , P_( n.P_ ) { } -nest::weight_recorder::Parameters_::Parameters_() +weight_recorder::Parameters_::Parameters_() : senders_() , targets_() { } void -nest::weight_recorder::Parameters_::get( DictionaryDatum& d ) const +weight_recorder::Parameters_::get( DictionaryDatum& d ) const { if ( senders_.get() ) { @@ -89,7 +91,7 @@ nest::weight_recorder::Parameters_::get( DictionaryDatum& d ) const } void -nest::weight_recorder::Parameters_::set( const DictionaryDatum& d ) +weight_recorder::Parameters_::set( const DictionaryDatum& d ) { if ( d->known( names::senders ) ) { @@ -137,25 +139,24 @@ nest::weight_recorder::Parameters_::set( const DictionaryDatum& d ) } void -nest::weight_recorder::pre_run_hook() +weight_recorder::pre_run_hook() { - RecordingDevice::pre_run_hook( - { nest::names::weights }, { nest::names::targets, nest::names::receptors, nest::names::ports } ); + RecordingDevice::pre_run_hook( { names::weights }, { names::targets, names::receptors, names::ports } ); } void -nest::weight_recorder::update( Time const&, const long, const long ) +weight_recorder::update( Time const&, const long, const long ) { } -nest::RecordingDevice::Type -nest::weight_recorder::get_type() const +RecordingDevice::Type +weight_recorder::get_type() const { return RecordingDevice::WEIGHT_RECORDER; } void -nest::weight_recorder::get_status( DictionaryDatum& d ) const +weight_recorder::get_status( DictionaryDatum& d ) const { // get the data from the device RecordingDevice::get_status( d ); @@ -181,7 +182,7 @@ nest::weight_recorder::get_status( DictionaryDatum& d ) const } void -nest::weight_recorder::set_status( const DictionaryDatum& d ) +weight_recorder::set_status( const DictionaryDatum& d ) { Parameters_ ptmp = P_; ptmp.set( d ); @@ -192,7 +193,7 @@ nest::weight_recorder::set_status( const DictionaryDatum& d ) void -nest::weight_recorder::handle( WeightRecorderEvent& e ) +weight_recorder::handle( WeightRecorderEvent& e ) { // accept spikes only if recorder was active when spike was emitted if ( is_active( e.get_stamp() ) ) @@ -212,3 +213,5 @@ nest::weight_recorder::handle( WeightRecorderEvent& e ) static_cast< long >( e.get_port() ) } ); } } + +} // namespace nest \ No newline at end of file diff --git a/modelsets/full b/modelsets/full index 46d6c6ee5a..422b595f5b 100644 --- a/modelsets/full +++ b/modelsets/full @@ -118,6 +118,7 @@ stdp_nn_pre_centered_synapse stdp_nn_restr_synapse stdp_nn_symm_synapse stdp_pl_synapse_hom +stdp_pl_synapse_hom_ax_delay stdp_synapse stdp_facetshw_synapse_hom stdp_synapse_hom diff --git a/nestkernel/CMakeLists.txt b/nestkernel/CMakeLists.txt index ab3257a89f..b24f2420b3 100644 --- a/nestkernel/CMakeLists.txt +++ b/nestkernel/CMakeLists.txt @@ -30,7 +30,7 @@ set ( nestkernel_sources connection.h connection_label.h common_properties_hom_w.h - syn_id_delay.h + delay_types.h connector_base.h connector_base_impl.h connector_model.h connector_model_impl.h connector_model.cpp connection_id.h connection_id.cpp diff --git a/nestkernel/archiving_node.cpp b/nestkernel/archiving_node.cpp index 7ad511eb3c..eb0484389d 100644 --- a/nestkernel/archiving_node.cpp +++ b/nestkernel/archiving_node.cpp @@ -33,7 +33,7 @@ namespace nest // member functions for ArchivingNode -nest::ArchivingNode::ArchivingNode() +ArchivingNode::ArchivingNode() : n_incoming_( 0 ) , Kminus_( 0.0 ) , Kminus_triplet_( 0.0 ) @@ -44,10 +44,14 @@ nest::ArchivingNode::ArchivingNode() , max_delay_( 0 ) , trace_( 0.0 ) , last_spike_( -1.0 ) + , has_predominant_stdp_ax_delay_( false ) { + const size_t num_time_slots = + kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(); + correction_entries_stdp_ax_delay_.resize( num_time_slots ); } -nest::ArchivingNode::ArchivingNode( const ArchivingNode& n ) +ArchivingNode::ArchivingNode( const ArchivingNode& n ) : StructuralPlasticityNode( n ) , n_incoming_( n.n_incoming_ ) , Kminus_( n.Kminus_ ) @@ -59,17 +63,42 @@ nest::ArchivingNode::ArchivingNode( const ArchivingNode& n ) , max_delay_( n.max_delay_ ) , trace_( n.trace_ ) , last_spike_( n.last_spike_ ) + , has_predominant_stdp_ax_delay_( false ) { + const size_t num_time_slots = + kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(); + correction_entries_stdp_ax_delay_.resize( num_time_slots ); } void -ArchivingNode::register_stdp_connection( double t_first_read, double delay ) +ArchivingNode::pre_run_hook_() +{ + if ( has_predominant_stdp_ax_delay_ ) + { + const size_t num_time_slots = + kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(); + if ( correction_entries_stdp_ax_delay_.size() != num_time_slots ) + { + correction_entries_stdp_ax_delay_.resize( num_time_slots ); + } + } +} + +void +ArchivingNode::register_stdp_connection( const double t_first_read, + const double dendritic_delay, + const double axonal_delay ) { // Mark all entries in the deque, which we will not read in future as read by // this input, so that we safely increment the incoming number of // connections afterwards without leaving spikes in the history. // For details see bug #218. MH 08-04-22 + if ( axonal_delay >= dendritic_delay ) + { + has_predominant_stdp_ax_delay_ = true; + } + for ( std::deque< histentry >::iterator runner = history_.begin(); runner != history_.end() and ( t_first_read - runner->t_ > -1.0 * kernel().connection_manager.get_stdp_eps() ); ++runner ) @@ -79,11 +108,11 @@ ArchivingNode::register_stdp_connection( double t_first_read, double delay ) n_incoming_++; - max_delay_ = std::max( delay, max_delay_ ); + max_delay_ = std::max( dendritic_delay + axonal_delay, max_delay_ ); } double -nest::ArchivingNode::get_K_value( double t ) +ArchivingNode::get_K_value( double t ) { // case when the neuron has not yet spiked if ( history_.empty() ) @@ -92,8 +121,7 @@ nest::ArchivingNode::get_K_value( double t ) return trace_; } - // search for the latest post spike in the history buffer that came strictly - // before `t` + // search for the latest post spike in the history buffer that came strictly before `t` int i = history_.size() - 1; while ( i >= 0 ) { @@ -112,10 +140,7 @@ nest::ArchivingNode::get_K_value( double t ) } void -nest::ArchivingNode::get_K_values( double t, - double& K_value, - double& nearest_neighbor_K_value, - double& K_triplet_value ) +ArchivingNode::get_K_values( double t, double& K_value, double& nearest_neighbor_K_value, double& K_triplet_value ) { // case when the neuron has not yet spiked if ( history_.empty() ) @@ -150,7 +175,7 @@ nest::ArchivingNode::get_K_values( double t, } void -nest::ArchivingNode::get_history( double t1, +ArchivingNode::get_history( double t1, double t2, std::deque< histentry >::iterator* start, std::deque< histentry >::iterator* finish ) @@ -178,7 +203,7 @@ nest::ArchivingNode::get_history( double t1, } void -nest::ArchivingNode::set_spiketime( Time const& t_sp, double offset ) +ArchivingNode::set_spiketime( Time const& t_sp, double offset ) { StructuralPlasticityNode::set_spiketime( t_sp, offset ); @@ -216,10 +241,12 @@ nest::ArchivingNode::set_spiketime( Time const& t_sp, double offset ) { last_spike_ = t_sp_ms; } + + correct_synapses_stdp_ax_delay_( t_sp ); } void -nest::ArchivingNode::get_status( DictionaryDatum& d ) const +ArchivingNode::get_status( DictionaryDatum& d ) const { def< double >( d, names::t_spike, get_spiketime_ms() ); def< double >( d, names::tau_minus, tau_minus_ ); @@ -234,7 +261,7 @@ nest::ArchivingNode::get_status( DictionaryDatum& d ) const } void -nest::ArchivingNode::set_status( const DictionaryDatum& d ) +ArchivingNode::set_status( const DictionaryDatum& d ) { // We need to preserve values in case invalid values are set double new_tau_minus = tau_minus_; @@ -265,7 +292,7 @@ nest::ArchivingNode::set_status( const DictionaryDatum& d ) } void -nest::ArchivingNode::clear_history() +ArchivingNode::clear_history() { last_spike_ = -1.0; Kminus_ = 0.0; @@ -273,5 +300,71 @@ nest::ArchivingNode::clear_history() history_.clear(); } +void +ArchivingNode::add_correction_entry_stdp_ax_delay( SpikeEvent& spike_event, + const double t_last_pre_spike, + const double weight_revert, + const double time_while_critical ) +{ + assert( correction_entries_stdp_ax_delay_.size() + == static_cast< size_t >( + kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay() ) ); + const long idx = kernel().event_delivery_manager.get_modulo( time_while_critical - 1 ); + assert( static_cast< size_t >( idx ) < correction_entries_stdp_ax_delay_.size() ); + + const SpikeData& spike_data = spike_event.get_sender_spike_data(); + correction_entries_stdp_ax_delay_[ idx ].push_back( + CorrectionEntrySTDPAxDelay( spike_data.get_lcid(), spike_data.get_syn_id(), t_last_pre_spike, weight_revert ) ); +} + +void +ArchivingNode::reset_correction_entries_stdp_ax_delay_() +{ + if ( has_predominant_stdp_ax_delay_ ) + { + const long mindelay_steps = kernel().connection_manager.get_min_delay(); + assert( correction_entries_stdp_ax_delay_.size() + == static_cast< size_t >( mindelay_steps + kernel().connection_manager.get_max_delay() ) ); + + for ( long lag = 0; lag < mindelay_steps; ++lag ) + { + const long idx = kernel().event_delivery_manager.get_modulo( lag ); + assert( static_cast< size_t >( idx ) < correction_entries_stdp_ax_delay_.size() ); + + std::vector< CorrectionEntrySTDPAxDelay >().swap( correction_entries_stdp_ax_delay_[ idx ] ); + } + } +} + +void +ArchivingNode::correct_synapses_stdp_ax_delay_( const Time& t_spike ) +{ + if ( has_predominant_stdp_ax_delay_ ) + { + const Time& ori = kernel().simulation_manager.get_slice_origin(); + const Time& t_spike_rel = t_spike - ori; + const long maxdelay_steps = kernel().connection_manager.get_max_delay(); + assert( correction_entries_stdp_ax_delay_.size() + == static_cast< size_t >( kernel().connection_manager.get_min_delay() + maxdelay_steps ) ); + + for ( long lag = t_spike_rel.get_steps() - 1; lag < maxdelay_steps + 1; ++lag ) + { + const long idx = kernel().event_delivery_manager.get_modulo( lag ); + assert( static_cast< size_t >( idx ) < correction_entries_stdp_ax_delay_.size() ); + + for ( CorrectionEntrySTDPAxDelay& it_corr_entry : correction_entries_stdp_ax_delay_[ idx ] ) + { + kernel().connection_manager.correct_synapse_stdp_ax_delay( get_thread(), + it_corr_entry.syn_id_, + it_corr_entry.lcid_, + it_corr_entry.t_last_pre_spike_, + it_corr_entry.weight_revert_, + t_spike.get_ms() ); + } + // indicate that the new spike was processed by these STDP synapses + history_.back().access_counter_ += correction_entries_stdp_ax_delay_[ idx ].size(); + } + } +} } // of namespace nest diff --git a/nestkernel/archiving_node.h b/nestkernel/archiving_node.h index 86b402ed1a..2e3778d569 100644 --- a/nestkernel/archiving_node.h +++ b/nestkernel/archiving_node.h @@ -92,12 +92,31 @@ class ArchivingNode : public StructuralPlasticityNode * t_first_read: The newly registered synapse will read the history entries * with t > t_first_read. */ - void register_stdp_connection( double t_first_read, double delay ) override; + void register_stdp_connection( const double t_first_read, + const double dendritic_delay, + const double axonal_delay ) override; void get_status( DictionaryDatum& d ) const override; void set_status( const DictionaryDatum& d ) override; + /** + * Framework for STDP with predominantly axonal delays: Buffer a correction entry for a short time window. + * + * @param spike_event Incoming pre-synaptic spike which could potentially need a correction after the next + * post-synaptic spike. + * @param t_last_pre_spike The time of the last pre-synaptic spike that was processed before the current one. + * @param weight_revert The synaptic weight before depression after facilitation as baseline for potential later + * correction. + * @param time_while_critical The number of time steps until the spike no longer needs to be corrected. + */ + void add_correction_entry_stdp_ax_delay( SpikeEvent& spike_event, + const double t_last_pre_spike, + const double weight_revert, + const double time_while_critical ); + protected: + void pre_run_hook_(); + /** * Record spike history */ @@ -113,6 +132,8 @@ class ArchivingNode : public StructuralPlasticityNode */ void clear_history(); + void reset_correction_entries_stdp_ax_delay_(); + /** * Number of incoming connections from STDP connectors. * @@ -142,6 +163,51 @@ class ArchivingNode : public StructuralPlasticityNode // spiking history needed by stdp synapses std::deque< histentry > history_; + + /** + * Framework for STDP with predominantly axonal delays: + * Due to the long axonal delays, relevant spikes of this neuron might not yet be available at the time when incoming + * synapses are updated (spike delivery). Therefore, for each spike received through an STDP synapse with + * predominantly axonal delay, information is stored for a short period of time allowing for retrospective correction + * of the synapse and the already delivered spike. + */ + struct CorrectionEntrySTDPAxDelay + { + CorrectionEntrySTDPAxDelay( const size_t lcid, + const synindex syn_id, + const double t_last_pre_spike, + const double weight_revert ) + : lcid_( lcid ) + , syn_id_( syn_id ) + , t_last_pre_spike_( t_last_pre_spike ) + , weight_revert_( weight_revert ) + { + } + + unsigned int lcid_; //!< local connection index + synindex syn_id_; //!< synapse-type index + double t_last_pre_spike_; //!< time of the last pre-synaptic spike before this spike + double weight_revert_; //!< synaptic weight to revert to (STDP depression needs to be undone) + }; + + //! check for correct correction entry size + using correction_entry_size = StaticAssert< sizeof( ArchivingNode::CorrectionEntrySTDPAxDelay ) == 24 >::success; + +protected: + /** + * Framework for STDP with predominantly axonal delays: + * Buffer of correction entries sorted by t_spike_pre + delay + * (i.e., the actual arrival time at this neuron). + */ + std::vector< std::vector< CorrectionEntrySTDPAxDelay > > correction_entries_stdp_ax_delay_; + //! false by default and set to true if any incoming connection has predominant axonal delays + bool has_predominant_stdp_ax_delay_; + + /** + * Framework for STDP with predominantly axonal delays: + * Triggered when this neuron spikes, to correct all relevant incoming STDP synapses with predominantly axonal delays + * and corresponding received spikes. */ + void correct_synapses_stdp_ax_delay_( const Time& t_spike ); }; inline double diff --git a/nestkernel/common_synapse_properties.cpp b/nestkernel/common_synapse_properties.cpp index 2a5053c0c3..c3ada8d3b7 100644 --- a/nestkernel/common_synapse_properties.cpp +++ b/nestkernel/common_synapse_properties.cpp @@ -25,7 +25,6 @@ // Includes from nestkernel: #include "connector_model.h" #include "nest_timeconverter.h" -#include "nest_types.h" #include "node.h" // Includes from models: diff --git a/nestkernel/common_synapse_properties.h b/nestkernel/common_synapse_properties.h index fab02945c6..4605190f8c 100644 --- a/nestkernel/common_synapse_properties.h +++ b/nestkernel/common_synapse_properties.h @@ -27,7 +27,6 @@ #include "connector_model.h" #include "nest_datums.h" #include "nest_types.h" -#include "node.h" // Includes from sli: #include "dictdatum.h" @@ -39,6 +38,7 @@ namespace nest // forward declarations class weight_recorder; class ConnectorModel; +class Node; class TimeConverter; /** @@ -104,7 +104,6 @@ CommonSynapseProperties::get_weight_recorder() const return weight_recorder_; } - } // of namespace nest #endif diff --git a/nestkernel/conn_builder.cpp b/nestkernel/conn_builder.cpp index f70f00f0b4..8a8a858a41 100644 --- a/nestkernel/conn_builder.cpp +++ b/nestkernel/conn_builder.cpp @@ -28,16 +28,18 @@ // Includes from nestkernel: #include "conn_builder_impl.h" #include "conn_parameter.h" +#include "connection.h" #include "connection_manager.h" +#include "delay_types.h" #include "exceptions.h" #include "kernel_manager.h" #include "nest_names.h" #include "node.h" +#include "target_identifier.h" #include "vp_manager_impl.h" // Includes from sli: #include "dict.h" -#include "fdstream.h" #include "name.h" // Includes from C++: @@ -146,15 +148,23 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, } // Synapse-specific parameters that should be skipped when we set default synapse parameters - skip_syn_params_ = { - names::weight, names::delay, names::min_delay, names::max_delay, names::num_connections, names::synapse_model - }; + skip_syn_params_ = { names::weight, + names::delay, + names::dendritic_delay, + names::axonal_delay, + names::min_delay, + names::max_delay, + names::num_connections, + names::synapse_model }; default_weight_.resize( syn_specs.size() ); default_delay_.resize( syn_specs.size() ); - default_weight_and_delay_.resize( syn_specs.size() ); + default_dendritic_delay_.resize( syn_specs.size() ); + default_axonal_delay_.resize( syn_specs.size() ); weights_.resize( syn_specs.size() ); delays_.resize( syn_specs.size() ); + dendritic_delays_.resize( syn_specs.size() ); + axonal_delays_.resize( syn_specs.size() ); synapse_params_.resize( syn_specs.size() ); synapse_model_id_.resize( syn_specs.size() ); synapse_model_id_[ 0 ] = kernel().model_manager.get_synapse_model_id( "static_synapse" ); @@ -166,7 +176,7 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, auto syn_params = syn_specs[ synapse_indx ]; set_synapse_model_( syn_params, synapse_indx ); - set_default_weight_or_delay_( syn_params, synapse_indx ); + set_default_weight_or_delays_( syn_params, synapse_indx ); DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); @@ -186,6 +196,8 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, { reset_weights_(); reset_delays_(); + reset_dendritic_delays_(); + reset_axonal_delays_(); for ( auto params : synapse_params_ ) { @@ -214,6 +226,16 @@ nest::BipartiteConnBuilder::~BipartiteConnBuilder() delete delay; } + for ( auto delay : dendritic_delays_ ) + { + delete delay; + } + + for ( auto delay : axonal_delays_ ) + { + delete delay; + } + for ( auto params : synapse_params_ ) { for ( auto synapse_parameter : params ) @@ -311,6 +333,8 @@ nest::BipartiteConnBuilder::connect() // call reset on all parameters reset_weights_(); reset_delays_(); + reset_dendritic_delays_(); + reset_axonal_delays_(); for ( auto params : synapse_params_ ) { @@ -397,45 +421,37 @@ nest::BipartiteConnBuilder::single_connect_( size_t snode_id, Node& target, size { update_param_dict_( snode_id, target, target_thread, rng, synapse_indx ); - if ( default_weight_and_delay_[ synapse_indx ] ) + double delay = numerics::nan; + double dendritic_delay = numerics::nan; + double axonal_delay = numerics::nan; + double weight = numerics::nan; + + if ( not default_delay_[ synapse_indx ] ) { - kernel().connection_manager.connect( snode_id, - &target, - target_thread, - synapse_model_id_[ synapse_indx ], - param_dicts_[ synapse_indx ][ target_thread ] ); + delay = delays_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); } - else if ( default_weight_[ synapse_indx ] ) + if ( not default_dendritic_delay_[ synapse_indx ] ) { - kernel().connection_manager.connect( snode_id, - &target, - target_thread, - synapse_model_id_[ synapse_indx ], - param_dicts_[ synapse_indx ][ target_thread ], - delays_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ) ); + dendritic_delay = dendritic_delays_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); } - else if ( default_delay_[ synapse_indx ] ) + if ( not default_axonal_delay_[ synapse_indx ] ) { - kernel().connection_manager.connect( snode_id, - &target, - target_thread, - synapse_model_id_[ synapse_indx ], - param_dicts_[ synapse_indx ][ target_thread ], - numerics::nan, - weights_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ) ); + axonal_delay = axonal_delays_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); } - else + if ( not default_weight_[ synapse_indx ] ) { - const double delay = delays_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); - const double weight = weights_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); - kernel().connection_manager.connect( snode_id, - &target, - target_thread, - synapse_model_id_[ synapse_indx ], - param_dicts_[ synapse_indx ][ target_thread ], - delay, - weight ); + weight = weights_[ synapse_indx ]->value_double( target_thread, rng, snode_id, &target ); } + + kernel().connection_manager.connect( snode_id, + &target, + target_thread, + synapse_model_id_[ synapse_indx ], + param_dicts_[ synapse_indx ][ target_thread ], + delay, + dendritic_delay, + axonal_delay, + weight ); } // We connect third-party only once per source-target pair, not per collocated synapse type @@ -480,6 +496,22 @@ nest::BipartiteConnBuilder::all_parameters_scalar_() const } } + for ( auto delay : dendritic_delays_ ) + { + if ( delay ) + { + all_scalar = all_scalar and delay->is_scalar(); + } + } + + for ( auto delay : axonal_delays_ ) + { + if ( delay ) + { + all_scalar = all_scalar and delay->is_scalar(); + } + } + for ( auto params : synapse_params_ ) { for ( auto synapse_parameter : params ) @@ -517,22 +549,24 @@ nest::BipartiteConnBuilder::set_synapse_model_( DictionaryDatum syn_params, size } void -nest::BipartiteConnBuilder::set_default_weight_or_delay_( DictionaryDatum syn_params, size_t synapse_indx ) +nest::BipartiteConnBuilder::set_default_weight_or_delays_( DictionaryDatum syn_params, size_t synapse_indx ) { DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); - // All synapse models have the possibility to set the delay (see SynIdDelay), but some have + // All synapse models have the possibility to set the delay, but some have // homogeneous weights, hence it should be possible to set the delay without the weight. default_weight_[ synapse_indx ] = not syn_params->known( names::weight ); - default_delay_[ synapse_indx ] = not syn_params->known( names::delay ); + // Based on the synapse type, it must not be allowed to specify either the total delay or axonal or dendritic delay. + kernel().model_manager.check_valid_default_delay_parameters( synapse_model_id_[ synapse_indx ], syn_params ); - // If neither weight nor delay are given in the dict, we handle this separately. Important for - // hom_w synapses, on which weight cannot be set. However, we use default weight and delay for - // _all_ types of synapses. - default_weight_and_delay_[ synapse_indx ] = ( default_weight_[ synapse_indx ] and default_delay_[ synapse_indx ] ); + default_delay_[ synapse_indx ] = not syn_params->known( names::delay ); + default_dendritic_delay_[ synapse_indx ] = not syn_params->known( names::dendritic_delay ); + default_axonal_delay_[ synapse_indx ] = not syn_params->known( names::axonal_delay ); - if ( not default_weight_and_delay_[ synapse_indx ] ) + // If neither weight nor delay are given in the dict, we handle this separately. Important for hom_w synapses, on + // which weight cannot be set. However, we use default weight and delay for _all_ types of synapses. + if ( not( default_weight_[ synapse_indx ] and default_delay_[ synapse_indx ] ) ) { weights_[ synapse_indx ] = syn_params->known( names::weight ) ? ConnParameter::create( ( *syn_params )[ names::weight ], kernel().vp_manager.get_num_threads() ) @@ -550,6 +584,22 @@ nest::BipartiteConnBuilder::set_default_weight_or_delay_( DictionaryDatum syn_pa : ConnParameter::create( ( *syn_defaults )[ names::delay ], kernel().vp_manager.get_num_threads() ); } register_parameters_requiring_skipping_( *delays_[ synapse_indx ] ); + + if ( not default_dendritic_delay_[ synapse_indx ] ) + { + dendritic_delays_[ synapse_indx ] = syn_params->known( names::dendritic_delay ) + ? ConnParameter::create( ( *syn_params )[ names::dendritic_delay ], kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( ( *syn_defaults )[ names::dendritic_delay ], kernel().vp_manager.get_num_threads() ); + register_parameters_requiring_skipping_( *dendritic_delays_[ synapse_indx ] ); + } + + if ( not default_axonal_delay_[ synapse_indx ] ) + { + axonal_delays_[ synapse_indx ] = syn_params->known( names::axonal_delay ) + ? ConnParameter::create( ( *syn_params )[ names::axonal_delay ], kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( ( *syn_defaults )[ names::axonal_delay ], kernel().vp_manager.get_num_threads() ); + register_parameters_requiring_skipping_( *axonal_delays_[ synapse_indx ] ); + } } void @@ -650,6 +700,30 @@ nest::BipartiteConnBuilder::reset_delays_() } } +void +nest::BipartiteConnBuilder::reset_dendritic_delays_() +{ + for ( auto delay : dendritic_delays_ ) + { + if ( delay ) + { + delay->reset(); + } + } +} + +void +nest::BipartiteConnBuilder::reset_axonal_delays_() +{ + for ( auto delay : axonal_delays_ ) + { + if ( delay ) + { + delay->reset(); + } + } +} + nest::ThirdInBuilder::ThirdInBuilder( NodeCollectionPTR sources, NodeCollectionPTR third, const DictionaryDatum& third_conn_spec, @@ -1031,8 +1105,7 @@ nest::OneToOneBuilder::connect_() } catch ( std::exception& err ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. + // We must create a new exception here, err's lifetime ends at the end of the catch block. exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } diff --git a/nestkernel/conn_builder.h b/nestkernel/conn_builder.h index 801d4bb355..7d24afc728 100644 --- a/nestkernel/conn_builder.h +++ b/nestkernel/conn_builder.h @@ -113,6 +113,26 @@ class BipartiteConnBuilder return default_delay_[ 0 ]; } + bool + get_default_dendritic_delay() const + { + if ( synapse_model_id_.size() > 1 ) + { + throw KernelException( "Can only retrieve default dendritic delay when one synapse per connection is used." ); + } + return default_dendritic_delay_[ 0 ]; + } + + bool + get_default_axonal_delay() const + { + if ( synapse_model_id_.size() > 1 ) + { + throw KernelException( "Can only retrieve default axonal delay when one synapse per connection is used." ); + } + return default_axonal_delay_[ 0 ]; + } + void set_synaptic_element_names( const std::string& pre_name, const std::string& post_name ); /** @@ -252,18 +272,23 @@ class BipartiteConnBuilder private: typedef std::map< Name, ConnParameter* > ConnParameterMap; - //! indicate that weight and delay should not be set per synapse - std::vector< bool > default_weight_and_delay_; - //! indicate that weight should not be set per synapse std::vector< bool > default_weight_; - //! indicate that delay should not be set per synapse + //! indicate that total delay should not be set per synapse std::vector< bool > default_delay_; + //! indicate that dendritic delay should not be set per synapse + std::vector< bool > default_dendritic_delay_; + + //! indicate that axonal delay should not be set per synapse + std::vector< bool > default_axonal_delay_; + // null-pointer indicates that default be used std::vector< ConnParameter* > weights_; std::vector< ConnParameter* > delays_; + std::vector< ConnParameter* > dendritic_delays_; + std::vector< ConnParameter* > axonal_delays_; //! all other parameters, mapping name to value representation std::vector< ConnParameterMap > synapse_params_; @@ -284,7 +309,7 @@ class BipartiteConnBuilder * Set synapse specific parameters. */ void set_synapse_model_( DictionaryDatum syn_params, size_t indx ); - void set_default_weight_or_delay_( DictionaryDatum syn_params, size_t indx ); + void set_default_weight_or_delays_( DictionaryDatum syn_params, size_t indx ); void set_synapse_params( DictionaryDatum syn_defaults, DictionaryDatum syn_params, size_t indx ); /** @@ -309,6 +334,8 @@ class BipartiteConnBuilder */ void reset_weights_(); void reset_delays_(); + void reset_dendritic_delays_(); + void reset_axonal_delays_(); }; diff --git a/nestkernel/conn_builder_conngen.cpp b/nestkernel/conn_builder_conngen.cpp index 7c0547ab34..ebc7297162 100644 --- a/nestkernel/conn_builder_conngen.cpp +++ b/nestkernel/conn_builder_conngen.cpp @@ -130,6 +130,8 @@ ConnectionGeneratorBuilder::connect_() synapse_model_id_[ 0 ], param_dicts_[ 0 ][ target_thread ], params[ d_idx ], + numerics::nan, + numerics::nan, params[ w_idx ] ); } } diff --git a/nestkernel/connection.h b/nestkernel/connection.h index 4a90eb2f0f..65d6564777 100644 --- a/nestkernel/connection.h +++ b/nestkernel/connection.h @@ -28,6 +28,7 @@ #include "connection_label.h" #include "connector_base_impl.h" #include "delay_checker.h" +#include "delay_types.h" #include "event.h" #include "kernel_manager.h" #include "nest.h" @@ -37,7 +38,7 @@ #include "nest_types.h" #include "node.h" #include "spikecounter.h" -#include "syn_id_delay.h" +#include "target_identifier.h" // Includes from sli: #include "arraydatum.h" @@ -76,7 +77,7 @@ class ConnTestDummyNodeBase : public Node { } void - update( const nest::Time&, long, long ) override + update( const nest::Time&, const long, const long ) override { } void @@ -111,7 +112,7 @@ class ConnTestDummyNodeBase : public Node * or if needs to be changed, everything has to be reset after sending * (i.e. after Event::operator() has been called). */ -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > class Connection { @@ -121,12 +122,15 @@ class Connection Connection() : target_() - , syn_id_delay_( 1.0 ) + , more_targets_( false ) + , disabled_( false ) + , delay_( 1.0 ) { + delay_.set_delay_ms( 1.0 ); } - Connection( const Connection< targetidentifierT >& rhs ) = default; - Connection& operator=( const Connection< targetidentifierT >& rhs ) = default; + Connection( const Connection< targetidentifierT, DelayTypeT >& rhs ) = default; + Connection& operator=( const Connection< targetidentifierT, DelayTypeT >& rhs ) = default; /** * Get a pointer to an instance of a SecondaryEvent if this connection supports secondary events. @@ -169,57 +173,122 @@ class Connection void calibrate( const TimeConverter& ); /** - * Return the delay of the connection in ms + * Framework for STDP with predominantly axonal delays: + * Correct this synapse and the corresponding previously sent spike + * taking into account a new post-synaptic spike. + */ + void correct_synapse_stdp_ax_delay( const size_t tid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike, + const CommonSynapseProperties& ); + + /** + * Return the proportion of the transmission delay attributed to the dendrite. */ double - get_delay() const + get_dendritic_delay_ms() const { - return syn_id_delay_.get_delay_ms(); + return delay_.get_dendritic_delay_ms(); } /** - * Return the delay of the connection in steps + * Return the proportion of the transmission delay attributed to the dendrite. */ long - get_delay_steps() const + get_dendritic_delay_steps() const { - return syn_id_delay_.delay; + return delay_.get_dendritic_delay_steps(); } /** - * Set the delay of the connection + * Set the proportion of the transmission delay attributed to the dendrite. */ void - set_delay( const double delay ) + set_dendritic_delay_ms( const double d ) { - syn_id_delay_.set_delay_ms( delay ); + delay_.set_dendritic_delay_ms( d ); } /** - * Set the delay of the connection in steps + * Set the proportion of the transmission delay attributed to the dendrite. + */ + void + set_dendritic_delay_steps( const long d ) + { + delay_.set_dendritic_delay_steps( d ); + } + + /** + * Set the proportion of the transmission delay attributed to the axon. */ void - set_delay_steps( const long delay ) + set_axonal_delay_ms( const double d ) + { + delay_.set_axonal_delay_ms( d ); + } + + /** + * Get the proportion of the transmission delay attributed to the axon. + */ + double + get_axonal_delay_ms() const { - syn_id_delay_.delay = delay; + return delay_.get_axonal_delay_ms(); } /** - * Set the synapse id of the connection + * Set the proportion of the transmission delay attributed to the axon. */ void - set_syn_id( synindex syn_id ) + set_axonal_delay_steps( const long d ) + { + delay_.set_axonal_delay_steps( d ); + } + + /** + * Get the proportion of the transmission delay attributed to the axon. + */ + double + get_axonal_delay_steps() const { - syn_id_delay_.syn_id = syn_id; + return delay_.get_axonal_delay_steps(); } /** - * Get the synapse id of the connection + * Return the delay of the connection in ms */ - synindex - get_syn_id() const + double + get_delay_ms() const { - return syn_id_delay_.syn_id; + return delay_.get_delay_ms(); + } + + /** + * Return the delay of the connection in steps + */ + long + get_delay_steps() const + { + return delay_.get_delay_steps(); + } + + /** + * Set the delay of the connection + */ + void + set_delay_ms( const double d ) + { + delay_.set_delay_ms( d ); + } + + /** + * Set the delay of the connection in steps + */ + void + set_delay_steps( const long d ) + { + delay_.set_delay_steps( d ); } long @@ -258,7 +327,7 @@ class Connection void set_source_has_more_targets( const bool more_targets ) { - syn_id_delay_.set_source_has_more_targets( more_targets ); + more_targets_ = more_targets; } /** @@ -270,29 +339,29 @@ class Connection bool source_has_more_targets() const { - return syn_id_delay_.source_has_more_targets(); + return more_targets_; } /** - * Disables the connection. + * Disables the synapse. * * @see is_disabled */ void disable() { - syn_id_delay_.disable(); + disabled_ = true; } /** - * Returns a flag denoting if the connection is disabled. + * Returns a flag denoting if the synapse is disabled. * * @see disable */ bool is_disabled() const { - return syn_id_delay_.is_disabled(); + return disabled_; } protected: @@ -305,39 +374,50 @@ class Connection * \param the last spike produced by the presynaptic neuron (for STDP and * maturing connections) */ - void check_connection_( Node& dummy_target, Node& source, Node& target, const size_t receptor_type ); + void check_connection_( Node& dummy_target, + Node& source, + Node& target, + const synindex syn_id, + const size_t receptor_type ); - // The order of the members below is critical as it influcences the size of the object. - // Please leave unchanged! targetidentifierT target_; - // syn_id (9 bit), delay (21 bit) in timesteps of this connection and more_targets and disabled flags (each 1 bit) - SynIdDelay syn_id_delay_; + bool more_targets_ : 1; + bool disabled_ : 1; + DelayTypeT delay_; + // There are still 14 bits to spare here. If more bits are required, the sizes of the delays in the delay struct could + // be reduced even more as well. }; -template < typename targetidentifierT > -constexpr ConnectionModelProperties Connection< targetidentifierT >::properties; +using success_connection_target_ptr_size = + StaticAssert< sizeof( Connection< TargetIdentifierPtrRport, TotalDelay > ) == 24 >::success; +using success_connection_target_idx_size = + StaticAssert< sizeof( Connection< TargetIdentifierIndex, TotalDelay > ) == 8 >::success; +using success_connection_target_ptr_size = + StaticAssert< sizeof( Connection< TargetIdentifierPtrRport, AxonalDendriticDelay > ) == 24 >::success; +using success_connection_target_idx_size = + StaticAssert< sizeof( Connection< TargetIdentifierIndex, AxonalDendriticDelay > ) == 8 >::success; + +template < typename targetidentifierT, typename DelayTypeT > +constexpr ConnectionModelProperties Connection< targetidentifierT, DelayTypeT >::properties; -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::check_connection_( Node& dummy_target, +Connection< targetidentifierT, DelayTypeT >::check_connection_( Node& dummy_target, Node& source, Node& target, + const synindex syn_id, const size_t receptor_type ) { - // 1. does this connection support the event type sent by source - // try to send event from source to dummy_target - // this line might throw an exception - source.send_test_event( dummy_target, receptor_type, get_syn_id(), true ); + // 1. does this connection support the event type sent by source try to send event from source to dummy_target this + // line might throw an exception + source.send_test_event( dummy_target, receptor_type, syn_id, true ); - // 2. does the target accept the event type sent by source - // try to send event from source to target - // this returns the port of the incoming connection - // p must be stored in the base class connection + // 2. does the target accept the event type sent by source try to send event from source to target + // this returns the port of the incoming connection p must be stored in the base class connection // this line might throw an exception - target_.set_rport( source.send_test_event( target, receptor_type, get_syn_id(), false ) ); + target_.set_rport( source.send_test_event( target, receptor_type, syn_id, false ) ); - // 3. do the events sent by source mean the same thing as they are - // interpreted in target? + // 3. do the events sent by source mean the same thing as they are interpreted in target? // note that we here use a bitwise and operation (&), because we interpret // each bit in the signal type as a collection of individual flags if ( not( source.sends_signal() & target.receives_signal() ) ) @@ -348,49 +428,49 @@ Connection< targetidentifierT >::check_connection_( Node& dummy_target, target_.set_target( &target ); } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::get_status( DictionaryDatum& d ) const +Connection< targetidentifierT, DelayTypeT >::get_status( DictionaryDatum& d ) const { - def< double >( d, names::delay, syn_id_delay_.get_delay_ms() ); + delay_.get_status( d ); target_.get_status( d ); } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& ) +Connection< targetidentifierT, DelayTypeT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) { - double delay; - if ( updateValue< double >( d, names::delay, delay ) ) - { - kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( delay ); - syn_id_delay_.set_delay_ms( delay ); - } + delay_.set_status( d, cm ); // no call to target_.set_status() because target and rport cannot be changed } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::check_synapse_params( const DictionaryDatum& ) const +Connection< targetidentifierT, DelayTypeT >::check_synapse_params( const DictionaryDatum& ) const { } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::calibrate( const TimeConverter& tc ) +Connection< targetidentifierT, DelayTypeT >::calibrate( const TimeConverter& tc ) { - Time t = tc.from_old_steps( syn_id_delay_.delay ); - syn_id_delay_.delay = t.get_steps(); + delay_.calibrate( tc ); +} - if ( syn_id_delay_.delay == 0 ) - { - syn_id_delay_.delay = 1; - } +template < typename targetidentifierT, typename DelayTypeT > +inline void +Connection< targetidentifierT, DelayTypeT >::correct_synapse_stdp_ax_delay( const size_t, + const double, + double&, + const double, + const CommonSynapseProperties& ) +{ + throw IllegalConnection( "Connection does not support correction in case of STDP with predominantly axonal delays." ); } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > inline void -Connection< targetidentifierT >::trigger_update_weight( const size_t, +Connection< targetidentifierT, DelayTypeT >::trigger_update_weight( const size_t, const std::vector< spikecounter >&, const double, const CommonSynapseProperties& ) @@ -398,9 +478,9 @@ Connection< targetidentifierT >::trigger_update_weight( const size_t, throw IllegalConnection( "Connection does not support updates that are triggered by a volume transmitter." ); } -template < typename targetidentifierT > +template < typename targetidentifierT, typename DelayTypeT > SecondaryEvent* -Connection< targetidentifierT >::get_secondary_event() +Connection< targetidentifierT, DelayTypeT >::get_secondary_event() { assert( false and "Non-primary connections have to provide get_secondary_event()" ); return nullptr; diff --git a/nestkernel/connection_creator.cpp b/nestkernel/connection_creator.cpp index 21b94e3153..10684ed854 100644 --- a/nestkernel/connection_creator.cpp +++ b/nestkernel/connection_creator.cpp @@ -36,6 +36,8 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) , synapse_model_() , weight_() , delay_() + , dendritic_delay_() + , axonal_delay_() { Name connection_type; @@ -111,9 +113,50 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) { weight_ = { NestModule::create_parameter( ( *syn_defaults )[ names::weight ] ) }; } + + // In case the synapse type uses split axonal and dendritic delays, the synapse default dict will contain values for + // the dendritic delay, the axonal delay, and also the total delay. But we only want to use the delay value if we are + // not explicitly using axonal and dendritic delays, so we only set the delay here if those are not provided. + bool axonal_or_dendritic_delay_set = false; + if ( dendritic_delay_.empty() ) + { + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) + or not syn_defaults->known( names::dendritic_delay ) ) + { + dendritic_delay_ = { NestModule::create_parameter( numerics::nan ) }; + } + else + { + dendritic_delay_ = { NestModule::create_parameter( ( *syn_defaults )[ names::dendritic_delay ] ) }; + axonal_or_dendritic_delay_set = true; + } + } + else + { + axonal_or_dendritic_delay_set = true; + } + if ( axonal_delay_.empty() ) + { + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) + or not syn_defaults->known( names::axonal_delay ) ) + { + axonal_delay_ = { NestModule::create_parameter( numerics::nan ) }; + } + else + { + axonal_delay_ = { NestModule::create_parameter( ( *syn_defaults )[ names::axonal_delay ] ) }; + axonal_or_dendritic_delay_set = true; + } + } + else + { + axonal_or_dendritic_delay_set = true; + } + if ( delay_.empty() ) { - if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) or not syn_defaults->known( names::delay ) + or axonal_or_dendritic_delay_set ) { delay_ = { NestModule::create_parameter( numerics::nan ) }; } @@ -183,10 +226,54 @@ ConnectionCreator::extract_params_( const DictionaryDatum& dict_datum, std::vect if ( dict_datum->known( names::delay ) ) { delay_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::delay ] ) ); + dendritic_delay_.push_back( NestModule::create_parameter( numerics::nan ) ); + axonal_delay_.push_back( NestModule::create_parameter( numerics::nan ) ); } else { - if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) + // In case the synapse type uses split axonal and dendritic delays, the synapse default dict will contain values for + // the dendritic delay, the axonal delay, and also the total delay. But we only want to use the delay value if we + // are not explicitly using axonal and dendritic delays, so we only set the delay here if those are not provided. + bool axonal_or_dendritic_delay_set = false; + if ( dict_datum->known( names::dendritic_delay ) ) + { + dendritic_delay_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::dendritic_delay ] ) ); + axonal_or_dendritic_delay_set = true; + } + else + { + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) + or not syn_defaults->known( names::dendritic_delay ) ) + { + dendritic_delay_.push_back( NestModule::create_parameter( numerics::nan ) ); + } + else + { + dendritic_delay_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::dendritic_delay ] ) ); + axonal_or_dendritic_delay_set = true; + } + } + if ( dict_datum->known( names::axonal_delay ) ) + { + axonal_delay_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::axonal_delay ] ) ); + axonal_or_dendritic_delay_set = true; + } + else + { + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) + or not syn_defaults->known( names::axonal_delay ) ) + { + axonal_delay_.push_back( NestModule::create_parameter( numerics::nan ) ); + } + else + { + axonal_delay_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::axonal_delay ] ) ); + axonal_or_dendritic_delay_set = true; + } + } + + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) or not syn_defaults->known( names::delay ) + or axonal_or_dendritic_delay_set ) { delay_.push_back( NestModule::create_parameter( numerics::nan ) ); } diff --git a/nestkernel/connection_creator.h b/nestkernel/connection_creator.h index 62d2671344..44e034eb41 100644 --- a/nestkernel/connection_creator.h +++ b/nestkernel/connection_creator.h @@ -186,6 +186,8 @@ class ConnectionCreator std::vector< std::vector< DictionaryDatum > > param_dicts_; std::vector< std::shared_ptr< Parameter > > weight_; std::vector< std::shared_ptr< Parameter > > delay_; + std::vector< std::shared_ptr< Parameter > > dendritic_delay_; + std::vector< std::shared_ptr< Parameter > > axonal_delay_; }; } // namespace nest diff --git a/nestkernel/connection_creator_impl.h b/nestkernel/connection_creator_impl.h index e094ab59d5..a8fba1cea2 100644 --- a/nestkernel/connection_creator_impl.h +++ b/nestkernel/connection_creator_impl.h @@ -108,6 +108,8 @@ ConnectionCreator::connect_to_target_( Iterator from, synapse_model_[ indx ], param_dicts_[ indx ][ tgt_thread ], delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + dendritic_delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + axonal_delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); } } @@ -153,6 +155,8 @@ ConnectionCreator::connect_to_target_poisson_( Iterator from, synapse_model_[ indx ], param_dicts_[ indx ][ tgt_thread ], delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + dendritic_delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + axonal_delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); } } @@ -258,7 +262,7 @@ ConnectionCreator::pairwise_bernoulli_on_source_( Layer< D >& source, NodeCollection::const_iterator target_begin = target_nc->begin(); NodeCollection::const_iterator target_end = target_nc->end(); - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); @@ -342,7 +346,7 @@ ConnectionCreator::pairwise_bernoulli_on_target_( Layer< D >& source, NodeCollection::const_iterator target_begin = target_nc->thread_local_begin(); NodeCollection::const_iterator target_end = target_nc->end(); - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); @@ -483,7 +487,7 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, // protect against connecting to devices without proxies // we need to do this before creating the first connection to leave // the network untouched if any target does not have proxies - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id ); @@ -497,7 +501,7 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, std::vector< std::pair< Position< D >, size_t > > positions; - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { size_t target_id = ( *tgt_it ).node_id; Node* const tgt = kernel().node_manager.get_node_or_proxy( target_id ); @@ -574,9 +578,20 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) { const double w = weight_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - const double d = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - kernel().connection_manager.connect( - source_id, tgt, target_thread, synapse_model_[ indx ], param_dicts_[ indx ][ target_thread ], d, w ); + const double delay = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double dend_delay = + dendritic_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double ax_delay = + axonal_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + kernel().connection_manager.connect( source_id, + tgt, + target_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ target_thread ], + delay, + dend_delay, + ax_delay, + w ); } is_selected[ random_id ] = true; @@ -613,9 +628,20 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) { const double w = weight_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - const double d = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - kernel().connection_manager.connect( - source_id, tgt, target_thread, synapse_model_[ indx ], param_dicts_[ indx ][ target_thread ], d, w ); + const double delay = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double dend_delay = + dendritic_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double ax_delay = + axonal_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + kernel().connection_manager.connect( source_id, + tgt, + target_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ target_thread ], + delay, + dend_delay, + ax_delay, + w ); } is_selected[ random_id ] = true; @@ -631,7 +657,7 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, // Get (position,node ID) pairs for all nodes in source layer std::vector< std::pair< Position< D >, size_t > >* positions = source.get_global_positions_vector( source_nc ); - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { size_t target_id = ( *tgt_it ).node_id; Node* const tgt = kernel().node_manager.get_node_or_proxy( target_id ); @@ -700,9 +726,20 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) { const double w = weight_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - const double d = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - kernel().connection_manager.connect( - source_id, tgt, target_thread, synapse_model_[ indx ], param_dicts_[ indx ][ target_thread ], d, w ); + const double delay = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double dend_delay = + dendritic_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double ax_delay = + axonal_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + kernel().connection_manager.connect( source_id, + tgt, + target_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ target_thread ], + delay, + dend_delay, + ax_delay, + w ); } is_selected[ random_id ] = true; @@ -737,9 +774,20 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) { const double w = weight_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - const double d = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); - kernel().connection_manager.connect( - source_id, tgt, target_thread, synapse_model_[ indx ], param_dicts_[ indx ][ target_thread ], d, w ); + const double delay = delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double dend_delay = + dendritic_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + const double ax_delay = + axonal_delay_[ indx ]->value( rng, source_pos_vector, target_pos_vector, source, tgt ); + kernel().connection_manager.connect( source_id, + tgt, + target_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ target_thread ], + delay, + dend_delay, + ax_delay, + w ); } is_selected[ random_id ] = true; @@ -772,7 +820,7 @@ ConnectionCreator::fixed_outdegree_( Layer< D >& source, NodeCollection::const_iterator target_begin = target_nc->rank_local_begin(); NodeCollection::const_iterator target_end = target_nc->end(); - for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it < target_end; ++tgt_it ) + for ( NodeCollection::const_iterator tgt_it = target_begin; tgt_it != target_end; ++tgt_it ) { Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id ); @@ -869,11 +917,17 @@ ConnectionCreator::fixed_outdegree_( Layer< D >& source, std::vector< double > rng_weight_vec; std::vector< double > rng_delay_vec; + std::vector< double > rng_dendritic_delay_vec; + std::vector< double > rng_axonal_delay_vec; for ( size_t indx = 0; indx < weight_.size(); ++indx ) { const auto tgt = kernel().node_manager.get_node_or_proxy( target_pos_node_id_pairs[ indx ].second ); rng_weight_vec.push_back( weight_[ indx ]->value( grng, source_pos_vector, target_pos_vector, target, tgt ) ); rng_delay_vec.push_back( delay_[ indx ]->value( grng, source_pos_vector, target_pos_vector, target, tgt ) ); + rng_dendritic_delay_vec.push_back( + dendritic_delay_[ indx ]->value( grng, source_pos_vector, target_pos_vector, target, tgt ) ); + rng_axonal_delay_vec.push_back( + axonal_delay_[ indx ]->value( grng, source_pos_vector, target_pos_vector, target, tgt ) ); } // Each VP has now decided to create this connection and drawn any random parameter values @@ -896,6 +950,8 @@ ConnectionCreator::fixed_outdegree_( Layer< D >& source, synapse_model_[ indx ], param_dicts_[ indx ][ target_thread ], rng_delay_vec[ indx ], + rng_dendritic_delay_vec[ indx ], + rng_axonal_delay_vec[ indx ], rng_weight_vec[ indx ] ); } } diff --git a/nestkernel/connection_manager.cpp b/nestkernel/connection_manager.cpp index 7228915296..7476810647 100644 --- a/nestkernel/connection_manager.cpp +++ b/nestkernel/connection_manager.cpp @@ -22,13 +22,9 @@ #include "connection_manager.h" -// Generated includes: -#include "config.h" - // C++ includes: #include #include -#include #include #include #include @@ -53,7 +49,6 @@ #include "eprop_archiving_node_recurrent.h" #include "exceptions.h" #include "kernel_manager.h" -#include "mpi_manager_impl.h" #include "nest_names.h" #include "node.h" #include "sonata_connector.h" @@ -68,7 +63,10 @@ #include "tokenutils.h" -nest::ConnectionManager::ConnectionManager() +namespace nest +{ + +ConnectionManager::ConnectionManager() : connruledict_( new Dictionary() ) , connbuilder_factories_() , thirdconnruledict_( new Dictionary() ) @@ -84,10 +82,11 @@ nest::ConnectionManager::ConnectionManager() , secondary_connections_exist_( false ) , check_secondary_connections_() , stdp_eps_( 1.0e-6 ) + , num_corrections_( 0 ) { } -nest::ConnectionManager::~ConnectionManager() +ConnectionManager::~ConnectionManager() { // Memory leak on purpose! // The ConnectionManager is deleted, when the network is deleted, and @@ -98,7 +97,7 @@ nest::ConnectionManager::~ConnectionManager() } void -nest::ConnectionManager::initialize( const bool adjust_number_of_threads_or_rng_only ) +ConnectionManager::initialize( const bool adjust_number_of_threads_or_rng_only ) { if ( not adjust_number_of_threads_or_rng_only ) { @@ -129,6 +128,7 @@ nest::ConnectionManager::initialize( const bool adjust_number_of_threads_or_rng_ connections_.resize( num_threads ); secondary_recv_buffer_pos_.resize( num_threads ); compressed_spike_data_.resize( 0 ); + have_nonzero_axonal_delays_.resize( num_threads, false ); has_primary_connections_ = false; check_primary_connections_.initialize( num_threads, false ); @@ -158,7 +158,7 @@ nest::ConnectionManager::initialize( const bool adjust_number_of_threads_or_rng_ } void -nest::ConnectionManager::finalize( const bool adjust_number_of_threads_or_rng_only ) +ConnectionManager::finalize( const bool adjust_number_of_threads_or_rng_only ) { source_table_.finalize(); target_table_.finalize(); @@ -167,6 +167,8 @@ nest::ConnectionManager::finalize( const bool adjust_number_of_threads_or_rng_on std::vector< std::vector< ConnectorBase* > >().swap( connections_ ); std::vector< std::vector< std::vector< size_t > > >().swap( secondary_recv_buffer_pos_ ); compressed_spike_data_.clear(); + num_corrections_ = 0; + have_nonzero_axonal_delays_.clear(); if ( not adjust_number_of_threads_or_rng_only ) { @@ -187,7 +189,7 @@ nest::ConnectionManager::finalize( const bool adjust_number_of_threads_or_rng_on } void -nest::ConnectionManager::set_status( const DictionaryDatum& d ) +ConnectionManager::set_status( const DictionaryDatum& d ) { for ( size_t i = 0; i < delay_checkers_.size(); ++i ) { @@ -211,14 +213,14 @@ nest::ConnectionManager::set_status( const DictionaryDatum& d ) } } -nest::DelayChecker& -nest::ConnectionManager::get_delay_checker() +DelayChecker& +ConnectionManager::get_delay_checker() { return delay_checkers_[ kernel().vp_manager.get_thread_id() ]; } void -nest::ConnectionManager::get_status( DictionaryDatum& dict ) +ConnectionManager::get_status( DictionaryDatum& dict ) { update_delay_extrema_(); def< double >( dict, names::min_delay, Time( Time::step( min_delay_ ) ).get_ms() ); @@ -229,6 +231,8 @@ nest::ConnectionManager::get_status( DictionaryDatum& dict ) def< bool >( dict, names::keep_source_table, keep_source_table_ ); def< bool >( dict, names::use_compressed_spikes, use_compressed_spikes_ ); + def< size_t >( dict, names::num_corrections, num_corrections_ ); + sw_construction_connect.get_status( dict, names::time_construction_connect, names::time_construction_connect_cpu ); ArrayDatum connection_rules; @@ -240,7 +244,7 @@ nest::ConnectionManager::get_status( DictionaryDatum& dict ) } DictionaryDatum -nest::ConnectionManager::get_synapse_status( const size_t source_node_id, +ConnectionManager::get_synapse_status( const size_t source_node_id, const size_t target_node_id, const size_t tid, const synindex syn_id, @@ -285,7 +289,7 @@ nest::ConnectionManager::get_synapse_status( const size_t source_node_id, } void -nest::ConnectionManager::set_synapse_status( const size_t source_node_id, +ConnectionManager::set_synapse_status( const size_t source_node_id, const size_t target_node_id, const size_t tid, const synindex syn_id, @@ -335,7 +339,7 @@ nest::ConnectionManager::set_synapse_status( const size_t source_node_id, } void -nest::ConnectionManager::delete_connections_() +ConnectionManager::delete_connections_() { for ( size_t tid = 0; tid < connections_.size(); ++tid ) { @@ -346,8 +350,8 @@ nest::ConnectionManager::delete_connections_() } } -const nest::Time -nest::ConnectionManager::get_min_delay_time_() const +const Time +ConnectionManager::get_min_delay_time_() const { Time min_delay = Time::pos_inf(); @@ -360,8 +364,8 @@ nest::ConnectionManager::get_min_delay_time_() const return min_delay; } -const nest::Time -nest::ConnectionManager::get_max_delay_time_() const +const Time +ConnectionManager::get_max_delay_time_() const { Time max_delay = Time::get_resolution(); @@ -375,7 +379,7 @@ nest::ConnectionManager::get_max_delay_time_() const } bool -nest::ConnectionManager::get_user_set_delay_extrema() const +ConnectionManager::get_user_set_delay_extrema() const { bool user_set_delay_extrema = false; @@ -388,8 +392,8 @@ nest::ConnectionManager::get_user_set_delay_extrema() const return user_set_delay_extrema; } -nest::BipartiteConnBuilder* -nest::ConnectionManager::get_conn_builder( const std::string& name, +BipartiteConnBuilder* +ConnectionManager::get_conn_builder( const std::string& name, NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, @@ -429,7 +433,7 @@ nest::ConnectionManager::get_third_conn_builder( const std::string& name, } void -nest::ConnectionManager::calibrate( const TimeConverter& tc ) +ConnectionManager::calibrate( const TimeConverter& tc ) { for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { @@ -438,7 +442,7 @@ nest::ConnectionManager::calibrate( const TimeConverter& tc ) } void -nest::ConnectionManager::connect( NodeCollectionPTR sources, +ConnectionManager::connect( NodeCollectionPTR sources, NodeCollectionPTR targets, const DictionaryDatum& conn_spec, const std::vector< DictionaryDatum >& syn_specs ) @@ -487,7 +491,7 @@ nest::ConnectionManager::connect( NodeCollectionPTR sources, void -nest::ConnectionManager::connect( TokenArray sources, TokenArray targets, const DictionaryDatum& syn_spec ) +ConnectionManager::connect( TokenArray sources, TokenArray targets, const DictionaryDatum& syn_spec ) { // Get synapse id size_t syn_id = 0; @@ -513,7 +517,7 @@ nest::ConnectionManager::connect( TokenArray sources, TokenArray targets, const void -nest::ConnectionManager::update_delay_extrema_() +ConnectionManager::update_delay_extrema_() { if ( kernel().simulation_manager.has_been_simulated() ) { @@ -533,9 +537,9 @@ nest::ConnectionManager::update_delay_extrema_() max_delay_ = std::max( max_delay_, kernel().sp_manager.builder_max_delay() ); } - // If the user explicitly set min/max_delay, this happend on all MPI ranks, + // If the user explicitly set min/max_delay, this happened on all MPI ranks, // so all ranks are up to date already. Also, once the user has set min/max_delay - // explicitly, Connect() cannot induce new extrema. Thuse, we only need to communicate + // explicitly, Connect() cannot induce new extrema. Thus, we only need to communicate // with other ranks if the user has not set the extrema and connections may have // been created. if ( not kernel().connection_manager.get_user_set_delay_extrema() @@ -560,12 +564,14 @@ nest::ConnectionManager::update_delay_extrema_() // node ID node thread syn_id dict delay weight void -nest::ConnectionManager::connect( const size_t snode_id, +ConnectionManager::connect( const size_t snode_id, Node* target, size_t target_thread, const synindex syn_id, const DictionaryDatum& params, const double delay, + const double dendritic_delay, + const double axonal_delay, const double weight ) { kernel().model_manager.assert_valid_syn_id( syn_id, kernel().vp_manager.get_thread_id() ); @@ -577,7 +583,7 @@ nest::ConnectionManager::connect( const size_t snode_id, switch ( connection_type ) { case CONNECT: - connect_( *source, *target, snode_id, target_thread, syn_id, params, delay, weight ); + connect_( *source, *target, snode_id, target_thread, syn_id, params, delay, dendritic_delay, axonal_delay, weight ); break; case CONNECT_FROM_DEVICE: connect_from_device_( *source, *target, target_thread, syn_id, params, delay, weight ); @@ -592,7 +598,7 @@ nest::ConnectionManager::connect( const size_t snode_id, // node_id node_id dict syn_id bool -nest::ConnectionManager::connect( const size_t snode_id, +ConnectionManager::connect( const size_t snode_id, const size_t tnode_id, const DictionaryDatum& params, const synindex syn_id ) @@ -633,10 +639,12 @@ nest::ConnectionManager::connect( const size_t snode_id, } void -nest::ConnectionManager::connect_arrays( long* sources, +ConnectionManager::connect_arrays( long* sources, long* targets, double* weights, double* delays, + double* dendritic_delays, + double* axonal_delays, std::vector< std::string >& p_keys, double* p_values, size_t n, @@ -692,7 +700,10 @@ nest::ConnectionManager::connect_arrays( long* sources, } // Increments pointers to weight and delay, if they are specified. - auto increment_wd = [ weights, delays ]( decltype( weights ) & w, decltype( delays ) & d ) + auto increment_wd = [ weights, delays, dendritic_delays, axonal_delays ]( decltype( weights ) & w, + decltype( delays ) & d, + decltype( dendritic_delays ) & dend, + decltype( axonal_delays ) & axonal ) { if ( weights ) { @@ -702,6 +713,14 @@ nest::ConnectionManager::connect_arrays( long* sources, { ++d; } + if ( dendritic_delays ) + { + ++dend; + } + if ( axonal_delays ) + { + ++axonal; + } }; // Set flag before entering parallel section in case we have fewer connections than ranks. @@ -719,8 +738,12 @@ nest::ConnectionManager::connect_arrays( long* sources, auto t = targets; auto w = weights; auto d = delays; + auto dend = dendritic_delays; + auto axonal = axonal_delays; double weight_buffer = numerics::nan; double delay_buffer = numerics::nan; + double dendritic_delay_buffer = numerics::nan; + double axonal_delay_buffer = numerics::nan; int index_counter = 0; // Index of the current connection, for connection parameters for ( ; s != sources + n; ++s, ++t, ++index_counter ) @@ -736,7 +759,7 @@ nest::ConnectionManager::connect_arrays( long* sources, auto target_node = kernel().node_manager.get_node_or_proxy( *t, tid ); if ( target_node->is_proxy() ) { - increment_wd( w, d ); + increment_wd( w, d, dend, axonal ); continue; } @@ -750,6 +773,14 @@ nest::ConnectionManager::connect_arrays( long* sources, { delay_buffer = *d; } + if ( dendritic_delays ) + { + dendritic_delay_buffer = *dend; + } + if ( axonal_delays ) + { + axonal_delay_buffer = *axonal; + } // Store the key-value pair of each parameter in the Dictionary. for ( auto& param_pointer_pair : param_pointers ) @@ -782,11 +813,19 @@ nest::ConnectionManager::connect_arrays( long* sources, } } - connect( *s, target_node, tid, synapse_model_id, param_dicts[ tid ], delay_buffer, weight_buffer ); + connect( *s, + target_node, + tid, + synapse_model_id, + param_dicts[ tid ], + delay_buffer, + dendritic_delay_buffer, + axonal_delay_buffer, + weight_buffer ); ALL_ENTRIES_ACCESSED( *param_dicts[ tid ], "connect_arrays", "Unread dictionary entries: " ); - increment_wd( w, d ); + increment_wd( w, d, dend, axonal ); } } catch ( std::exception& err ) @@ -891,6 +930,8 @@ nest::ConnectionManager::connect_( Node& source, const synindex syn_id, const DictionaryDatum& params, const double delay, + const double dendritic_delay, + const double axonal_delay, const double weight ) { ConnectorModel& conn_model = kernel().model_manager.get_connection_model( syn_id, tid ); @@ -918,11 +959,14 @@ nest::ConnectionManager::connect_( Node& source, } const bool is_primary = conn_model.has_property( ConnectionModelProperties::IS_PRIMARY ); - conn_model.add_connection( source, target, connections_[ tid ], syn_id, params, delay, weight ); + conn_model.add_connection( + source, target, connections_[ tid ], syn_id, params, delay, dendritic_delay, axonal_delay, weight ); source_table_.add_source( tid, syn_id, s_node_id, is_primary ); increase_connection_count( tid, syn_id ); + have_nonzero_axonal_delays_[ tid ] = have_nonzero_axonal_delays_[ tid ] or ( axonal_delay > 0. ); + // We do not check has_primary_connections_ and secondary_connections_exist_ // directly as this led to worse performance on the supercomputer Piz Daint. if ( check_primary_connections_[ tid ].is_false() and is_primary ) @@ -940,7 +984,7 @@ nest::ConnectionManager::connect_( Node& source, } void -nest::ConnectionManager::connect_to_device_( Node& source, +ConnectionManager::connect_to_device_( Node& source, Node& target, const size_t s_node_id, const size_t tid, @@ -956,7 +1000,7 @@ nest::ConnectionManager::connect_to_device_( Node& source, } void -nest::ConnectionManager::connect_from_device_( Node& source, +ConnectionManager::connect_from_device_( Node& source, Node& target, const size_t tid, const synindex syn_id, @@ -971,7 +1015,7 @@ nest::ConnectionManager::connect_from_device_( Node& source, } void -nest::ConnectionManager::increase_connection_count( const size_t tid, const synindex syn_id ) +ConnectionManager::increase_connection_count( const size_t tid, const synindex syn_id ) { if ( num_connections_[ tid ].size() <= syn_id ) { @@ -989,7 +1033,7 @@ nest::ConnectionManager::increase_connection_count( const size_t tid, const syni } size_t -nest::ConnectionManager::find_connection( const size_t tid, +ConnectionManager::find_connection( const size_t tid, const synindex syn_id, const size_t snode_id, const size_t tnode_id ) @@ -1014,10 +1058,7 @@ nest::ConnectionManager::find_connection( const size_t tid, } void -nest::ConnectionManager::disconnect( const size_t tid, - const synindex syn_id, - const size_t snode_id, - const size_t tnode_id ) +ConnectionManager::disconnect( const size_t tid, const synindex syn_id, const size_t snode_id, const size_t tnode_id ) { assert( syn_id != invalid_synindex ); @@ -1036,7 +1077,7 @@ nest::ConnectionManager::disconnect( const size_t tid, } void -nest::ConnectionManager::trigger_update_weight( const long vt_id, +ConnectionManager::trigger_update_weight( const long vt_id, const std::vector< spikecounter >& dopa_spikes, const double t_trig ) { @@ -1054,7 +1095,7 @@ nest::ConnectionManager::trigger_update_weight( const long vt_id, } size_t -nest::ConnectionManager::get_num_target_data( const size_t tid ) const +ConnectionManager::get_num_target_data( const size_t tid ) const { size_t num_connections = 0; for ( synindex syn_id = 0; syn_id < connections_[ tid ].size(); ++syn_id ) @@ -1068,7 +1109,7 @@ nest::ConnectionManager::get_num_target_data( const size_t tid ) const } size_t -nest::ConnectionManager::get_num_connections() const +ConnectionManager::get_num_connections() const { size_t num_connections = 0; for ( size_t t = 0; t < num_connections_.size(); ++t ) @@ -1083,7 +1124,7 @@ nest::ConnectionManager::get_num_connections() const } size_t -nest::ConnectionManager::get_num_connections( const synindex syn_id ) const +ConnectionManager::get_num_connections( const synindex syn_id ) const { size_t num_connections = 0; for ( size_t t = 0; t < num_connections_.size(); ++t ) @@ -1098,7 +1139,7 @@ nest::ConnectionManager::get_num_connections( const synindex syn_id ) const } ArrayDatum -nest::ConnectionManager::get_connections( const DictionaryDatum& params ) +ConnectionManager::get_connections( const DictionaryDatum& params ) { std::deque< ConnectionID > connectome; const Token& source_t = params->lookup( names::source ); @@ -1180,8 +1221,8 @@ nest::ConnectionManager::get_connections( const DictionaryDatum& params ) // Helper method which removes ConnectionIDs from input deque and // appends them to output deque. -static inline std::deque< nest::ConnectionID >& -extend_connectome( std::deque< nest::ConnectionID >& out, std::deque< nest::ConnectionID >& in ) +static inline std::deque< ConnectionID >& +extend_connectome( std::deque< ConnectionID >& out, std::deque< ConnectionID >& in ) { while ( not in.empty() ) { @@ -1193,7 +1234,7 @@ extend_connectome( std::deque< nest::ConnectionID >& out, std::deque< nest::Conn } void -nest::ConnectionManager::split_to_neuron_device_vectors_( const size_t tid, +ConnectionManager::split_to_neuron_device_vectors_( const size_t tid, NodeCollectionPTR nodecollection, std::vector< size_t >& neuron_node_ids, std::vector< size_t >& device_node_ids ) const @@ -1218,7 +1259,7 @@ nest::ConnectionManager::split_to_neuron_device_vectors_( const size_t tid, } void -nest::ConnectionManager::get_connections( std::deque< ConnectionID >& connectome, +ConnectionManager::get_connections( std::deque< ConnectionID >& connectome, NodeCollectionPTR source, NodeCollectionPTR target, synindex syn_id, @@ -1403,7 +1444,7 @@ nest::ConnectionManager::get_connections( std::deque< ConnectionID >& connectome } void -nest::ConnectionManager::get_source_node_ids_( const size_t tid, +ConnectionManager::get_source_node_ids_( const size_t tid, const synindex syn_id, const size_t tnode_id, std::vector< size_t >& sources ) @@ -1417,7 +1458,7 @@ nest::ConnectionManager::get_source_node_ids_( const size_t tid, } void -nest::ConnectionManager::get_sources( const std::vector< size_t >& targets, +ConnectionManager::get_sources( const std::vector< size_t >& targets, const size_t syn_id, std::vector< std::vector< size_t > >& sources ) { @@ -1437,7 +1478,7 @@ nest::ConnectionManager::get_sources( const std::vector< size_t >& targets, } void -nest::ConnectionManager::get_targets( const std::vector< size_t >& sources, +ConnectionManager::get_targets( const std::vector< size_t >& sources, const size_t syn_id, const std::string& post_synaptic_element, std::vector< std::vector< size_t > >& targets ) @@ -1462,7 +1503,7 @@ nest::ConnectionManager::get_targets( const std::vector< size_t >& sources, } void -nest::ConnectionManager::sort_connections( const size_t tid ) +ConnectionManager::sort_connections( const size_t tid ) { assert( not source_table_.is_cleared() ); if ( use_compressed_spikes_ ) @@ -1479,7 +1520,7 @@ nest::ConnectionManager::sort_connections( const size_t tid ) } void -nest::ConnectionManager::compute_target_data_buffer_size() +ConnectionManager::compute_target_data_buffer_size() { // Determine number of target data on this rank. Since each thread // has its own data structures, we need to count connections on every @@ -1505,7 +1546,7 @@ nest::ConnectionManager::compute_target_data_buffer_size() } void -nest::ConnectionManager::compute_compressed_secondary_recv_buffer_positions( const size_t tid ) +ConnectionManager::compute_compressed_secondary_recv_buffer_positions( const size_t tid ) { #pragma omp single { @@ -1547,8 +1588,8 @@ nest::ConnectionManager::compute_compressed_secondary_recv_buffer_positions( con } } -nest::ConnectionManager::ConnectionType -nest::ConnectionManager::connection_required( Node*& source, Node*& target, size_t tid ) +ConnectionManager::ConnectionType +ConnectionManager::connection_required( Node*& source, Node*& target, size_t tid ) { // The caller has to check and guarantee that the target is not a // proxy and that it is on thread tid. @@ -1640,9 +1681,9 @@ nest::ConnectionManager::connection_required( Node*& source, Node*& target, size } void -nest::ConnectionManager::set_stdp_eps( const double stdp_eps ) +ConnectionManager::set_stdp_eps( const double stdp_eps ) { - if ( not( stdp_eps < Time::get_resolution().get_ms() ) ) + if ( stdp_eps >= Time::get_resolution().get_ms() ) { throw KernelException( "The epsilon used for spike-time comparison in STDP must be less " @@ -1669,7 +1710,7 @@ nest::ConnectionManager::set_stdp_eps( const double stdp_eps ) // recv_buffer can not be a const reference as iterators used in // secondary events must not be const bool -nest::ConnectionManager::deliver_secondary_events( const size_t tid, +ConnectionManager::deliver_secondary_events( const size_t tid, const bool called_from_wfr_update, std::vector< unsigned int >& recv_buffer ) { @@ -1717,13 +1758,13 @@ nest::ConnectionManager::deliver_secondary_events( const size_t tid, } void -nest::ConnectionManager::compress_secondary_send_buffer_pos( const size_t tid ) +ConnectionManager::compress_secondary_send_buffer_pos( const size_t tid ) { target_table_.compress_secondary_send_buffer_pos( tid ); } void -nest::ConnectionManager::remove_disabled_connections( const size_t tid ) +ConnectionManager::remove_disabled_connections( const size_t tid ) { std::vector< ConnectorBase* >& connectors = connections_[ tid ]; @@ -1747,7 +1788,7 @@ nest::ConnectionManager::remove_disabled_connections( const size_t tid ) } void -nest::ConnectionManager::resize_connections() +ConnectionManager::resize_connections() { kernel().vp_manager.assert_thread_parallel(); @@ -1758,19 +1799,19 @@ nest::ConnectionManager::resize_connections() } void -nest::ConnectionManager::sync_has_primary_connections() +ConnectionManager::sync_has_primary_connections() { has_primary_connections_ = kernel().mpi_manager.any_true( has_primary_connections_ ); } void -nest::ConnectionManager::check_secondary_connections_exist() +ConnectionManager::check_secondary_connections_exist() { secondary_connections_exist_ = kernel().mpi_manager.any_true( secondary_connections_exist_ ); } void -nest::ConnectionManager::set_connections_have_changed() +ConnectionManager::set_connections_have_changed() { assert( kernel().vp_manager.get_thread_id() == 0 ); @@ -1787,14 +1828,14 @@ nest::ConnectionManager::set_connections_have_changed() } void -nest::ConnectionManager::unset_connections_have_changed() +ConnectionManager::unset_connections_have_changed() { connections_have_changed_ = false; } void -nest::ConnectionManager::collect_compressed_spike_data( const size_t tid ) +ConnectionManager::collect_compressed_spike_data( const size_t tid ) { if ( use_compressed_spikes_ ) { @@ -1946,3 +1987,5 @@ nest::ConnectionManager::initialize_iteration_state() iteration_state_.push_back( std::pair< size_t, std::map< size_t, CSDMapEntry >::const_iterator >( 0, begin ) ); } } + +} diff --git a/nestkernel/connection_manager.h b/nestkernel/connection_manager.h index 49a8a8ca39..6c707e9abb 100644 --- a/nestkernel/connection_manager.h +++ b/nestkernel/connection_manager.h @@ -145,7 +145,9 @@ class ConnectionManager : public ManagerInterface * \param target_thread Thread that hosts the target node. * \param syn_id The synapse model to use. * \param params Parameter dictionary to configure the synapse. - * \param delay Delay of the connection (in ms). + * \param delay Total delay of the connection (in ms). + * \param dendritic_delay Dendritic delay of the connection (in ms). + * \param axonal_delay Axonal delay of the connection (in ms). * \param weight Weight of the connection. */ void connect( const size_t snode_id, @@ -154,6 +156,8 @@ class ConnectionManager : public ManagerInterface const synindex syn_id, const DictionaryDatum& params, const double delay = numerics::nan, + const double dendritic_delay = numerics::nan, + const double axonal_delay = numerics::nan, const double weight = numerics::nan ); /** @@ -174,6 +178,8 @@ class ConnectionManager : public ManagerInterface long* targets, double* weights, double* delays, + double* dendritic_delays, + double* axonal_delays, std::vector< std::string >& p_keys, double* p_values, size_t n, @@ -307,6 +313,26 @@ class ConnectionManager : public ManagerInterface const std::vector< ConnectorModel* >& cm, Event& e ); + /** + * On occurrence of a post-synaptic spike, correct the weight update of a previous pre-synaptic spike which was + * processed before the current post-synaptic spike, but had to be processed after it, if it was known at this point + * in time. + * + * @param tid The thread storing the synapse. + * @param syn_id Synapse type. + * @param lcid Local index of the synapse in the array of connections of the same type for this thread. + * @param t_last_pre_spike Time of the last pre-synaptic spike before the pre-synaptic spike which needs a correction. + * @param weight_revert The synaptic weight before depression after facilitation as baseline for potential later + * correction. + * @param t_post_spike Time of the current post-synaptic spike. + */ + void correct_synapse_stdp_ax_delay( const size_t tid, + const synindex syn_id, + const size_t lcid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike ); + /** * Send event e to all device targets of source source_node_id */ @@ -318,11 +344,6 @@ class ConnectionManager : public ManagerInterface */ void send_from_device( const size_t tid, const size_t ldid, Event& e ); - /** - * Send event e to all targets of node source on thread t - */ - void send_local( size_t t, Node& source, Event& e ); - /** * Resize the structures for the Connector objects if necessary. * @@ -396,31 +417,28 @@ class ConnectionManager : public ManagerInterface void remove_disabled_connections( const size_t tid ); /** - * Returns true if connection information needs to be - * communicated. False otherwise. + * Returns true if connection information needs to be communicated. False otherwise. */ bool connections_have_changed() const; /** - * Sets flag indicating whether connection information needs to be - * communicated to true. + * Sets flag indicating whether connection information needs to be communicated to true. */ void set_connections_have_changed(); /** - * Sets flag indicating whether connection information needs to be - * communicated to false. + * Sets flag indicating whether connection information needs to be communicated to false. */ void unset_connections_have_changed(); + bool have_nonzero_axonal_delays() const; + /** - * Deletes TargetTable and resets processed flags of - * SourceTable. + * Deletes TargetTable and resets processed flags of SourceTable. * - * This function must be called if connections are - * created after connections have been communicated previously. It - * basically restores the connection infrastructure to a state where - * all information only exists on the postsynaptic side. + * This function must be called if connections are created after connections have been communicated previously. It + * basically restores the connection infrastructure to a state where all information only exists on the postsynaptic + * side. */ void restructure_connection_tables( const size_t tid ); @@ -527,7 +545,9 @@ class ConnectionManager : public ManagerInterface * \param tid The thread of the target node. * \param syn_id The synapse model to use. * \param params The parameters for the connection. - * \param delay The delay of the connection (optional). + * \param delay Total delay of the connection (in ms). + * \param dendritic_delay Dendritic delay of the connection (in ms). + * \param axonal_delay Axonal delay of the connection (in ms). * \param weight The weight of the connection (optional). */ void connect_( Node& source, @@ -537,6 +557,8 @@ class ConnectionManager : public ManagerInterface const synindex syn_id, const DictionaryDatum& params, const double delay = numerics::nan, + const double dendritic_delay = numerics::nan, + const double axonal_delay = numerics::nan, const double weight = numerics::nan ); /** @@ -563,17 +585,17 @@ class ConnectionManager : public ManagerInterface const size_t tid, const synindex syn_id, const DictionaryDatum& params, - const double delay = NAN, - const double weight = NAN ); + const double delay = numerics::nan, + const double weight = numerics::nan ); /** * connect_from_device_ is used to establish a connection between a sender and * receiving node if the sender does not have proxies. * - * The parameters delay and weight have the default value NAN. - * NAN is a special value in cmath, which describes double values that + * The parameters delay and weight have the default value numerics::nan. + * numerics::nan is a special value in C++, which describes double values that * are not a number. If delay or weight is omitted in an connect call, - * NAN indicates this and weight/delay are set only, if they are valid. + * numerics::nan indicates this and weight/delay are set only, if they are valid. * * \param source A reference to the sending Node. * \param target A reference to the receiving Node. @@ -589,8 +611,8 @@ class ConnectionManager : public ManagerInterface const size_t tid, const synindex syn_id, const DictionaryDatum& params, - const double delay = NAN, - const double weight = NAN ); + const double delay = numerics::nan, + const double weight = numerics::nan ); /** * Increases the connection count. @@ -665,6 +687,9 @@ class ConnectionManager : public ManagerInterface //! simulate. bool connections_have_changed_; + //! True if any connection uses axonal delays on given thread. + std::vector< bool > have_nonzero_axonal_delays_; + //! true if GetConnections has been called. bool get_connections_has_been_called_; @@ -697,6 +722,9 @@ class ConnectionManager : public ManagerInterface //! For each thread, store (syn_id, compressed_spike_data_map_::iterator) pair for next iteration while filling target //! buffers std::vector< std::pair< size_t, std::map< size_t, CSDMapEntry >::const_iterator > > iteration_state_; + + //! Number of weight corrections required for STDP synapses with predominant axonal delays during the whole simulation + size_t num_corrections_; }; inline bool @@ -807,6 +835,13 @@ ConnectionManager::connections_have_changed() const return connections_have_changed_; } +inline bool +ConnectionManager::have_nonzero_axonal_delays() const +{ + return std::any_of( + have_nonzero_axonal_delays_.cbegin(), have_nonzero_axonal_delays_.cend(), []( const bool b ) { return b; } ); +} + inline void ConnectionManager::add_target( const size_t tid, const size_t target_rank, const TargetData& target_data ) { @@ -897,6 +932,19 @@ ConnectionManager::send( const size_t tid, connections_[ tid ][ syn_id ]->send( tid, lcid, cm, e ); } +inline void +ConnectionManager::correct_synapse_stdp_ax_delay( const size_t tid, + const synindex syn_id, + const size_t lcid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike ) +{ + ++num_corrections_; + connections_[ tid ][ syn_id ]->correct_synapse_stdp_ax_delay( + tid, syn_id, lcid, t_last_pre_spike, weight_revert, t_post_spike ); +} + inline void ConnectionManager::restructure_connection_tables( const size_t tid ) { diff --git a/nestkernel/connector_base.h b/nestkernel/connector_base.h index 7cdd91b1e8..712978bb13 100644 --- a/nestkernel/connector_base.h +++ b/nestkernel/connector_base.h @@ -54,12 +54,12 @@ namespace nest { /** - * Base class to allow storing Connectors for different synapse types - * in vectors. We define the interface here to avoid casting. + * Base class to allow storing Connectors for different synapse types in vectors. We define the interface here to avoid + * casting. * - * @note If any member functions need to do something special for a given connection type, - * declare specializations in the corresponding header file and define them in the corresponding - * source file. For an example, see `eprop_synapse_bsshslm_2020`. + * @note If any member functions need to do something special for a given connection type, declare specializations in + * the corresponding header file and define them in the corresponding source file. For an example, see + * `eprop_synapse_bsshslm_2020`. */ class ConnectorBase { @@ -71,8 +71,7 @@ class ConnectorBase virtual ~ConnectorBase() {}; /** - * Return syn_id_ of the synapse type of this Connector (index in - * list of synapse prototypes). + * Return syn_id_ of the synapse type of this Connector (index in list of synapse prototypes). */ virtual synindex get_syn_id() const = 0; @@ -82,21 +81,18 @@ class ConnectorBase virtual size_t size() const = 0; /** - * Write status of the connection at position lcid to the dictionary - * dict. + * Write status of the connection at position lcid to the dictionary dict. */ virtual void get_synapse_status( const size_t tid, const size_t lcid, DictionaryDatum& dict ) const = 0; /** - * Set status of the connection at position lcid according to the - * dictionary dict. + * Set status of the connection at position lcid according to the dictionary dict. */ virtual void set_synapse_status( const size_t lcid, const DictionaryDatum& dict, ConnectorModel& cm ) = 0; /** - * Add ConnectionID with given source_node_id and lcid to conns. If - * target_node_id is given, only add connection if target_node_id matches - * the node_id of the target of the connection. + * Add ConnectionID with given source_node_id and lcid to conns. If target_node_id is given, only add connection if + * target_node_id matches the node_id of the target of the connection. */ virtual void get_connection( const size_t source_node_id, const size_t target_node_id, @@ -106,9 +102,8 @@ class ConnectorBase std::deque< ConnectionID >& conns ) const = 0; /** - * Add ConnectionID with given source_node_id and lcid to conns. If - * target_neuron_node_ids is given, only add connection if - * target_neuron_node_ids contains the node ID of the target of the connection. + * Add ConnectionID with given source_node_id and lcid to conns. If target_neuron_node_ids is given, only add + * connection if target_neuron_node_ids contains the node ID of the target of the connection. */ virtual void get_connection_with_specified_targets( const size_t source_node_id, const std::vector< size_t >& target_neuron_node_ids, @@ -118,9 +113,8 @@ class ConnectorBase std::deque< ConnectionID >& conns ) const = 0; /** - * Add ConnectionIDs with given source_node_id to conns, looping over - * all lcids. If target_node_id is given, only add connection if - * target_node_id matches the node ID of the target of the connection. + * Add ConnectionIDs with given source_node_id to conns, looping over all lcids. If target_node_id is given, only add + * connection if target_node_id matches the node ID of the target of the connection. */ virtual void get_all_connections( const size_t source_node_id, const size_t target_node_id, @@ -129,15 +123,13 @@ class ConnectorBase std::deque< ConnectionID >& conns ) const = 0; /** - * For a given target_node_id add lcids of all connections with matching - * node ID of target to source_lcids. + * For a given target_node_id add lcids of all connections with matching node ID of target to source_lcids. */ virtual void get_source_lcids( const size_t tid, const size_t target_node_id, std::vector< size_t >& source_lcids ) const = 0; /** - * For a given start_lcid add node IDs of all targets that belong to the - * same source to target_node_ids. + * For a given start_lcid add node IDs of all targets that belong to the same source to target_node_ids. */ virtual void get_target_node_ids( const size_t tid, const size_t start_lcid, @@ -155,12 +147,31 @@ class ConnectorBase virtual void send_to_all( const size_t tid, const std::vector< ConnectorModel* >& cm, Event& e ) = 0; /** - * Send the event e to the connection at position lcid. Return bool - * indicating whether the following connection belongs to the same - * source. + * Send the event e to the connection at position lcid. Return bool indicating whether the following connection + * belongs to the same source. */ virtual size_t send( const size_t tid, const size_t lcid, const std::vector< ConnectorModel* >& cm, Event& e ) = 0; + /** + * On occurrence of a post-synaptic spike, correct the weight update of a previous pre-synaptic spike which was + * processed before the current post-synaptic spike, but had to be processed after it, if it was known at this point + * in time. + * + * @param tid The thread storing the synapse. + * @param syn_id Synapse type. + * @param lcid Local index of the synapse in the array of connections of the same type for this thread. + * @param t_last_pre_spike Time of the last pre-synaptic spike before the pre-synaptic spike which needs a correction. + * @param weight_revert The synaptic weight before depression after facilitation as baseline for potential later + * correction. + * @param t_post_spike Time of the current post-synaptic spike. + */ + virtual void correct_synapse_stdp_ax_delay( const size_t tid, + const synindex syn_id, + const size_t lcid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike ) = 0; + virtual void send_weight_event( const size_t tid, const unsigned int lcid, Event& e, const CommonSynapseProperties& cp ) = 0; @@ -179,31 +190,26 @@ class ConnectorBase virtual void sort_connections( BlockVector< Source >& ) = 0; /** - * Set a flag in the connection indicating whether the following - * connection belongs to the same source. + * Set a flag in the connection indicating whether the following connection belongs to the same source. */ virtual void set_source_has_more_targets( const size_t lcid, const bool has_more_targets ) = 0; /** - * Return lcid of the first connection after start_lcid (inclusive) - * where the node_id of the target matches target_node_id. If there are no matches, - * the function returns invalid_index. + * Return lcid of the first connection after start_lcid (inclusive) where the node_id of the target matches + * target_node_id. If there are no matches, the function returns invalid_index. */ virtual size_t find_first_target( const size_t tid, const size_t start_lcid, const size_t target_node_id ) const = 0; /** - * Return lcid of first connection where the node ID of the target - * matches target_node_id; consider only the connections with lcids - * given in matching_lcids. If there is no match, the function returns - * invalid_index. + * Return lcid of first connection where the node ID of the target matches target_node_id; consider only the + * connections with lcids given in matching_lcids. If there is no match, the function returns invalid_index. */ virtual size_t find_matching_target( const size_t tid, const std::vector< size_t >& matching_lcids, const size_t target_node_id ) const = 0; /** - * Disable the transfer of events through the connection at position - * lcid. + * Disable the transfer of events through the connection at position lcid. */ virtual void disable_connection( const size_t lcid ) = 0; @@ -408,6 +414,9 @@ class Connector : public ConnectorBase e.set_port( lcid + lcid_offset ); if ( not conn.is_disabled() ) { + // non-local sender -> receiver retrieves ID of sender Node from SourceTable based on tid, syn_id, lcid + // only if needed, as this is computationally costly + e.set_sender_node_id_info( tid, syn_id_, lcid + lcid_offset ); // Some synapses, e.g., bernoulli_synapse, may not send an event after all const bool event_sent = conn.send( e, tid, cp ); if ( event_sent ) @@ -425,6 +434,13 @@ class Connector : public ConnectorBase return 1 + lcid_offset; // event was delivered to at least one target } + void correct_synapse_stdp_ax_delay( const size_t tid, + const synindex syn_id, + const size_t lcid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike ) override; + // Implemented in connector_base_impl.h void send_weight_event( const size_t tid, const unsigned int lcid, Event& e, const CommonSynapseProperties& cp ) override; diff --git a/nestkernel/connector_base_impl.h b/nestkernel/connector_base_impl.h index 1c1b77a28f..fd61453293 100644 --- a/nestkernel/connector_base_impl.h +++ b/nestkernel/connector_base_impl.h @@ -61,6 +61,21 @@ Connector< ConnectionT >::send_weight_event( const size_t tid, } } +template < typename ConnectionT > +void +Connector< ConnectionT >::correct_synapse_stdp_ax_delay( const size_t tid, + const synindex syn_id, + const size_t lcid, + const double t_last_pre_spike, + double& weight_revert, + const double t_post_spike ) +{ + typename ConnectionT::CommonPropertiesType const& cp = static_cast< GenericConnectorModel< ConnectionT >* >( + kernel().model_manager.get_connection_models( tid )[ syn_id ] ) + ->get_common_properties(); + C_[ lcid ].correct_synapse_stdp_ax_delay( tid, t_last_pre_spike, weight_revert, t_post_spike, cp ); +} + } // of namespace nest #endif diff --git a/nestkernel/connector_model.h b/nestkernel/connector_model.h index 0a7f83ce8e..c92d6184b9 100644 --- a/nestkernel/connector_model.h +++ b/nestkernel/connector_model.h @@ -98,8 +98,10 @@ class ConnectorModel std::vector< ConnectorBase* >& hetconn, const synindex syn_id, const DictionaryDatum& d, - const double delay = NAN, - const double weight = NAN ) = 0; + const double delay = numerics::nan, + const double dendritic_delay = numerics::nan, + const double axonal_delay = numerics::nan, + const double weight = numerics::nan ) = 0; virtual ConnectorModel* clone( std::string, synindex syn_id ) const = 0; @@ -119,6 +121,8 @@ class ConnectorModel */ virtual void check_synapse_params( const DictionaryDatum& ) const = 0; + virtual void check_valid_default_delay_parameters( DictionaryDatum syn_params ) const = 0; + virtual SecondaryEvent* get_secondary_event() = 0; virtual size_t get_syn_id() const = 0; @@ -157,11 +161,13 @@ class GenericConnectorModel : public ConnectorModel ConnectionT default_connection_; size_t receptor_type_; + synindex syn_id_; public: GenericConnectorModel( const std::string name ) : ConnectorModel( name, ConnectionT::properties ) , receptor_type_( 0 ) + , syn_id_( invalid_synindex ) { } @@ -170,6 +176,7 @@ class GenericConnectorModel : public ConnectorModel , cp_( cm.cp_ ) , default_connection_( cm.default_connection_ ) , receptor_type_( cm.receptor_type_ ) + , syn_id_( cm.syn_id_ ) { } @@ -179,6 +186,8 @@ class GenericConnectorModel : public ConnectorModel const synindex syn_id, const DictionaryDatum& d, const double delay, + const double dendritic_delay, + const double axonal_delay, const double weight ) override; ConnectorModel* clone( std::string, synindex ) const override; @@ -199,6 +208,8 @@ class GenericConnectorModel : public ConnectorModel void check_synapse_params( const DictionaryDatum& syn_spec ) const override; + void check_valid_default_delay_parameters( DictionaryDatum syn_params ) const override; + SecondaryEvent* get_secondary_event() override { @@ -213,15 +224,7 @@ class GenericConnectorModel : public ConnectorModel private: void used_default_delay(); - - void add_connection_( Node& src, - Node& tgt, - std::vector< ConnectorBase* >& hetconn, - const synindex syn_id, - ConnectionT& c, - const size_t receptor_type ); - -}; // GenericConnectorModel +}; } // namespace nest diff --git a/nestkernel/connector_model_impl.h b/nestkernel/connector_model_impl.h index fc831cb916..22888b0bc7 100644 --- a/nestkernel/connector_model_impl.h +++ b/nestkernel/connector_model_impl.h @@ -33,8 +33,10 @@ #include "enum_bitfield.h" // Includes from nestkernel: +#include "connection.h" #include "connector_base.h" #include "delay_checker.h" +#include "delay_types.h" #include "kernel_manager.h" #include "nest_time.h" #include "nest_timeconverter.h" @@ -46,22 +48,6 @@ namespace nest { -// standard implementation to obtain the default delay -// synapse types with homogeneous delays must provide a specialization -// that returns the default delay from CommonProperties (or from else where) -// template -// double get_default_delay(const GenericConnectorModel &cm) -// { -// //std::cout << "standard implementation of get_default_delay" << std::endl; -// return cm.get_default_connection().get_delay(); -// } - -// template -// SynIdDelay & syn_id_delay(const GenericConnectorModel &cm) -// { -// return cm.get_default_connection().get_syn_id_delay(); -// } - template < typename ConnectionT > ConnectorModel* GenericConnectorModel< ConnectionT >::clone( std::string name, synindex syn_id ) const @@ -129,12 +115,12 @@ GenericConnectorModel< ConnectionT >::set_status( const DictionaryDatum& d ) kernel().connection_manager.get_delay_checker().freeze_delay_update(); cp_.set_status( d, *this ); + default_connection_.set_status( d, *this ); kernel().connection_manager.get_delay_checker().enable_delay_update(); - // we've possibly just got a new default delay. So enforce checking next time - // it is used + // we've possibly just got a new default delay. So enforce checking next time it is used default_delay_needs_check_ = true; } @@ -175,7 +161,7 @@ GenericConnectorModel< ConnectionT >::used_default_delay() { if ( has_property( ConnectionModelProperties::HAS_DELAY ) ) { - const double d = default_connection_.get_delay(); + const double d = default_connection_.get_delay_ms(); kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( d ); } // Let connections without delay contribute to the delay extrema with @@ -192,9 +178,8 @@ GenericConnectorModel< ConnectionT >::used_default_delay() } catch ( BadDelay& e ) { - throw BadDelay( default_connection_.get_delay(), - String::compose( "Default delay of '%1' must be between min_delay %2 " - "and max_delay %3.", + throw BadDelay( default_connection_.get_delay_ms(), + String::compose( "Default delay of '%1' must be between min_delay %2 and max_delay %3.", get_name(), Time::delay_steps_to_ms( kernel().connection_manager.get_min_delay() ), Time::delay_steps_to_ms( kernel().connection_manager.get_max_delay() ) ) ); @@ -207,14 +192,39 @@ template < typename ConnectionT > size_t GenericConnectorModel< ConnectionT >::get_syn_id() const { - return default_connection_.get_syn_id(); + return syn_id_; } template < typename ConnectionT > void GenericConnectorModel< ConnectionT >::set_syn_id( synindex syn_id ) { - default_connection_.set_syn_id( syn_id ); + syn_id_ = syn_id; +} + +template < typename ConnectionT > +void +GenericConnectorModel< ConnectionT >::check_valid_default_delay_parameters( DictionaryDatum syn_params ) const +{ + if constexpr ( std::is_base_of< Connection< TargetIdentifierPtrRport, AxonalDendriticDelay >, ConnectionT >::value + or std::is_base_of< Connection< TargetIdentifierIndex, AxonalDendriticDelay >, ConnectionT >::value ) + { + if ( syn_params->known( names::delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting total transmission delay." ); + } + } + else + { + if ( syn_params->known( names::dendritic_delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting dendritic delay." ); + } + if ( syn_params->known( names::axonal_delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting axonal delay." ); + } + } } template < typename ConnectionT > @@ -225,58 +235,105 @@ GenericConnectorModel< ConnectionT >::add_connection( Node& src, const synindex syn_id, const DictionaryDatum& p, const double delay, + const double dendritic_delay, + const double axonal_delay, const double weight ) { - if ( not numerics::is_nan( delay ) ) + // create a new instance of the default connection + ConnectionT connection = ConnectionT( default_connection_ ); + + bool default_delay_used = true; + + if ( has_property( ConnectionModelProperties::HAS_DELAY ) ) { - if ( has_property( ConnectionModelProperties::HAS_DELAY ) ) + if constexpr ( std::is_base_of< Connection< TargetIdentifierPtrRport, AxonalDendriticDelay >, ConnectionT >::value + or std::is_base_of< Connection< TargetIdentifierIndex, AxonalDendriticDelay >, ConnectionT >::value ) { - kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( delay ); - } + if ( not numerics::is_nan( delay ) or p->known( names::delay ) ) + { + throw BadProperty( "Setting the total transmission delay via the parameter '" + names::delay.toString() + + "' is not allowed for synapse types which use both dendritic and axonal delays, because of ambiguity." ); + } - if ( p->known( names::delay ) ) - { - throw BadParameter( - "Parameter dictionary must not contain delay if delay is given " - "explicitly." ); - } - } - else - { - // check delay - double delay = 0.0; + if ( not numerics::is_nan( dendritic_delay ) and p->known( names::dendritic_delay ) ) + { + throw BadParameter( + "Parameter dictionary must not contain dendritic delay if dendritic delay is given explicitly." ); + } - if ( updateValue< double >( p, names::delay, delay ) ) - { - if ( has_property( ConnectionModelProperties::HAS_DELAY ) ) + if ( not numerics::is_nan( axonal_delay ) and p->known( names::axonal_delay ) ) + { + throw BadParameter( "Parameter dictionary must not contain axonal delay if axonal delay is given explicitly." ); + } + + double actual_dendritic_delay = dendritic_delay; + double actual_axonal_delay = axonal_delay; + if ( not numerics::is_nan( dendritic_delay ) + or updateValue< double >( p, names::dendritic_delay, actual_dendritic_delay ) ) { - kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( delay ); + connection.set_dendritic_delay_ms( actual_dendritic_delay ); + } + if ( not numerics::is_nan( axonal_delay ) + or updateValue< double >( p, names::axonal_delay, actual_axonal_delay ) ) + { + connection.set_axonal_delay_ms( axonal_delay ); + } + if ( not numerics::is_nan( actual_dendritic_delay ) or not numerics::is_nan( actual_axonal_delay ) ) + { + default_delay_used = false; } } else { - used_default_delay(); + if ( not numerics::is_nan( dendritic_delay ) or p->known( names::dendritic_delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting dendritic delay." ); + } + + if ( not numerics::is_nan( axonal_delay ) or p->known( names::axonal_delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting axonal delay." ); + } + + if ( not numerics::is_nan( delay ) and ( p->known( names::delay ) or p->known( names::dendritic_delay ) ) ) + { + throw BadParameter( "Parameter dictionary must not contain delay if delay is given explicitly." ); + } + + double actual_delay = delay; + if ( updateValue< double >( p, names::delay, actual_delay ) or not numerics::is_nan( delay ) ) + { + connection.set_delay_ms( actual_delay ); + default_delay_used = false; + } } } - - // create a new instance of the default connection - ConnectionT connection = ConnectionT( default_connection_ ); + else if ( p->known( names::delay ) or p->known( names::dendritic_delay ) or p->known( names::axonal_delay ) + or not numerics::is_nan( delay ) or not numerics::is_nan( dendritic_delay ) + or not numerics::is_nan( axonal_delay ) ) + { + throw BadProperty( "Delay specified for a connection type which doesn't use delays." ); + } if ( not numerics::is_nan( weight ) ) { connection.set_weight( weight ); } - if ( not numerics::is_nan( delay ) ) + if ( not p->empty() ) { - connection.set_delay( delay ); + // Reference to connector model needed here to check delay (maybe this could be done one level above?). + connection.set_status( p, *this ); } - if ( not p->empty() ) + if ( has_property( ConnectionModelProperties::HAS_DELAY ) ) { - // Reference to connector model needed here to check delay (maybe this could - // be done one level above?). - connection.set_status( p, *this ); + kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( connection.get_delay_ms() ); + } + + if ( default_delay_used ) + { + used_default_delay(); } // We must use a local variable here to hold the actual value of the @@ -288,20 +345,6 @@ GenericConnectorModel< ConnectionT >::add_connection( Node& src, updateValue< long >( p, names::music_channel, actual_receptor_type ); #endif updateValue< long >( p, names::receptor_type, actual_receptor_type ); - - add_connection_( src, tgt, thread_local_connectors, syn_id, connection, actual_receptor_type ); -} - - -template < typename ConnectionT > -void -GenericConnectorModel< ConnectionT >::add_connection_( Node& src, - Node& tgt, - std::vector< ConnectorBase* >& thread_local_connectors, - const synindex syn_id, - ConnectionT& connection, - const size_t receptor_type ) -{ assert( syn_id != invalid_synindex ); if ( not thread_local_connectors[ syn_id ] ) @@ -313,7 +356,7 @@ GenericConnectorModel< ConnectionT >::add_connection_( Node& src, ConnectorBase* connector = thread_local_connectors[ syn_id ]; // The following line will throw an exception, if it does not work. - connection.check_connection( src, tgt, receptor_type, get_common_properties() ); + connection.check_connection( src, tgt, actual_receptor_type, syn_id, get_common_properties() ); assert( connector ); diff --git a/nestkernel/delay_checker.cpp b/nestkernel/delay_checker.cpp index 8a1776c98e..ff6268337c 100644 --- a/nestkernel/delay_checker.cpp +++ b/nestkernel/delay_checker.cpp @@ -161,9 +161,7 @@ nest::DelayChecker::assert_valid_delay_ms( double requested_new_delay ) const bool bad_max_delay = new_delay > kernel().connection_manager.get_max_delay(); if ( bad_min_delay or bad_max_delay ) { - throw BadDelay( new_delay_ms, - "Minimum and maximum delay cannot be changed " - "after Simulate has been called." ); + throw BadDelay( new_delay_ms, "Minimum and maximum delay cannot be changed after Simulate has been called." ); } } @@ -175,8 +173,7 @@ nest::DelayChecker::assert_valid_delay_ms( double requested_new_delay ) if ( user_set_delay_extrema_ ) { throw BadDelay( new_delay_ms, - "Delay must be greater than or equal to min_delay. " - "You may set min_delay before creating connections." ); + "Delay must be greater than or equal to min_delay. You may set min_delay before creating connections." ); } else { @@ -192,8 +189,7 @@ nest::DelayChecker::assert_valid_delay_ms( double requested_new_delay ) if ( user_set_delay_extrema_ ) { throw BadDelay( new_delay_ms, - "Delay must be smaller than or equal to max_delay. " - "You may set min_delay before creating connections." ); + "Delay must be smaller than or equal to max_delay. You may set min_delay before creating connections." ); } else { @@ -240,8 +236,7 @@ nest::DelayChecker::assert_two_valid_delays_steps( long new_delay1, long new_del if ( user_set_delay_extrema_ ) { throw BadDelay( Time::delay_steps_to_ms( ldelay ), - "Delay must be greater than or equal to min_delay. " - "You may set min_delay before creating connections." ); + "Delay must be greater than or equal to min_delay. You may set min_delay before creating connections." ); } else { @@ -257,8 +252,7 @@ nest::DelayChecker::assert_two_valid_delays_steps( long new_delay1, long new_del if ( user_set_delay_extrema_ ) { throw BadDelay( Time::delay_steps_to_ms( hdelay ), - "Delay must be smaller than or equal to max_delay. " - "You may set max_delay before creating connections." ); + "Delay must be smaller than or equal to max_delay. You may set max_delay before creating connections." ); } else { diff --git a/nestkernel/delay_types.h b/nestkernel/delay_types.h new file mode 100644 index 0000000000..903a1bd541 --- /dev/null +++ b/nestkernel/delay_types.h @@ -0,0 +1,373 @@ +/* + * delay_types.h + * + * This file is part of NEST. + * + * Copyright (C) 2004 The NEST Initiative + * + * NEST is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * NEST is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NEST. If not, see . + * + */ + +#ifndef DELAY_TYPES_H +#define DELAY_TYPES_H + +// Includes from nestkernel: +#include "kernel_manager.h" +#include "nest_time.h" +#include "nest_types.h" + +namespace nest +{ + + +/** + * Container for a single delay value which is interpreted as total transmission delay or purely dendritic delay by some + * models. Implies an axonal delay of 0. + */ +struct TotalDelay +{ + uint32_t delay_; + + explicit TotalDelay( double d ) + { + set_delay_ms( d ); + } + + /** + * Return the dendritic delay of the connection in steps + */ + long + get_dendritic_delay_steps() const + { + throw BadProperty( "Trying to get dendritic delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Set the dendritic delay of the connection specified in ms + */ + void + set_dendritic_delay_steps( const double ) + { + throw BadProperty( "Trying to set dendritic delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Return the dendritic delay of the connection in ms + */ + double + get_dendritic_delay_ms() const + { + throw BadProperty( "Trying to get dendritic delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Set the dendritic delay of the connection specified in ms + */ + void + set_dendritic_delay_ms( const double ) + { + throw BadProperty( "Trying to set dendritic delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Return the axonal delay of the connection in steps + */ + long + get_axonal_delay_steps() const + { + throw BadProperty( "Trying to get axonal delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Set the axonal delay of the connection specified in ms + */ + void + set_axonal_delay_steps( const double ) + { + throw BadProperty( "Trying to set axonal delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Return the axonal delay of the connection in ms + */ + double + get_axonal_delay_ms() const + { + throw BadProperty( "Trying to get axonal delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Set the axonal delay of the connection specified in ms + */ + void + set_axonal_delay_ms( const double ) + { + throw BadProperty( "Trying to set axonal delay on a synapse which only stores the total transmission delay." ); + } + + /** + * Return the delay of the connection in steps + */ + long + get_delay_steps() const + { + return delay_; + } + + /** + * Set the delay of the connection specified in ms + */ + void + set_delay_steps( const long d ) + { + delay_ = d; + } + + /** + * Return the delay of the connection in ms + */ + double + get_delay_ms() const + { + return Time::delay_steps_to_ms( delay_ ); + } + + /** + * Set the delay of the connection specified in ms + */ + void + set_delay_ms( const double d ) + { + delay_ = Time::delay_ms_to_steps( d ); + } + + void + calibrate( const TimeConverter& tc ) + { + Time t = tc.from_old_steps( delay_ ); + delay_ = t.get_steps(); + + if ( delay_ == 0 ) + { + delay_ = 1; + } + } + + void + get_status( DictionaryDatum& d ) const + { + def< double >( d, names::delay, Time::delay_steps_to_ms( delay_ ) ); + } + + void + set_status( const DictionaryDatum& d, ConnectorModel& ) + { + // Check for allowed combinations. See PR #2989 for more details. + if ( d->known( names::dendritic_delay ) or d->known( names::axonal_delay ) ) + { + throw BadParameter( "Synapse type does not support explicitly setting axonal and dendritic delays." ); + } + + // Update delay values + double delay; + if ( updateValue< double >( d, names::delay, delay ) ) + { + set_delay_ms( delay ); + } + + kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( get_delay_ms() ); + } +}; + +//! check legal size +using success_total_transmission_delay_data_size = StaticAssert< sizeof( TotalDelay ) == 4 >::success; + +/** + * Container for explicit dendritic and axonal delay values. + */ +struct AxonalDendriticDelay +{ + uint32_t dendritic_delay_ : NUM_BITS_DENDRITIC_DELAY; + uint32_t axonal_delay_ : NUM_BITS_AXONAL_DELAY; + + explicit AxonalDendriticDelay( double d ) + : axonal_delay_( 0 ) + { + set_dendritic_delay_ms( d ); + } + + /** + * Return the dendritic delay of the connection in steps + */ + long + get_dendritic_delay_steps() const + { + return dendritic_delay_; + } + + /** + * Set the dendritic delay of the connection specified in ms + */ + void + set_dendritic_delay_steps( const long d ) + { + dendritic_delay_ = d; + } + + /** + * Return the dendritic delay of the connection in ms + */ + double + get_dendritic_delay_ms() const + { + return Time::delay_steps_to_ms( dendritic_delay_ ); + } + + /** + * Set the dendritic delay of the connection specified in ms + */ + void + set_dendritic_delay_ms( const double d ) + { + dendritic_delay_ = Time::delay_ms_to_steps( d ); + } + + /** + * Return the axonal delay of the connection in steps + */ + long + get_axonal_delay_steps() const + { + return axonal_delay_; + } + + /** + * Set the axonal delay of the connection specified in ms + */ + void + set_axonal_delay_steps( const long d ) + { + axonal_delay_ = d; + } + + /** + * Return the axonal delay of the connection in ms + */ + double + get_axonal_delay_ms() const + { + return Time::delay_steps_to_ms( axonal_delay_ ); + } + + /** + * Set the axonal delay of the connection specified in ms + */ + void + set_axonal_delay_ms( const double d ) + { + axonal_delay_ = Time::delay_ms_to_steps( d ); + } + + /** + * Return the delay of the connection in steps + */ + long + get_delay_steps() const + { + return dendritic_delay_ + axonal_delay_; + } + + /** + * Set the delay of the connection specified in ms + */ + void + set_delay_steps( const long d ) + { + dendritic_delay_ = d; + axonal_delay_ = 0; + } + + /** + * Return the delay of the connection in ms + */ + double + get_delay_ms() const + { + return Time::delay_steps_to_ms( get_delay_steps() ); + } + + /** + * Set the delay of the connection specified in ms + */ + void + set_delay_ms( const double d ) + { + dendritic_delay_ = Time::delay_ms_to_steps( d ); + axonal_delay_ = 0; + } + + void + calibrate( const TimeConverter& tc ) + { + Time ax_delay_t = tc.from_old_steps( axonal_delay_ ); + Time dend_delay_t = tc.from_old_steps( dendritic_delay_ ); + axonal_delay_ = ax_delay_t.get_steps(); + dendritic_delay_ = dend_delay_t.get_steps(); + + if ( dendritic_delay_ == 0 ) + { + dendritic_delay_ = 1; + } + } + + void + get_status( DictionaryDatum& d ) const + { + def< double >( d, names::dendritic_delay, Time::delay_steps_to_ms( dendritic_delay_ ) ); + def< double >( d, names::axonal_delay, Time::delay_steps_to_ms( axonal_delay_ ) ); + def< double >( d, names::delay, Time::delay_steps_to_ms( axonal_delay_ + dendritic_delay_ ) ); + } + + void + set_status( const DictionaryDatum& d, ConnectorModel& ) + { + if ( d->known( names::delay ) ) + { + throw BadParameter( "Setting the total transmission delay via the parameter '" + names::delay.toString() + + "' is not allowed for synapse types which use both dendritic and axonal delays, because of ambiguity." ); + } + + // Update delay values + double dendritic_delay = get_dendritic_delay_ms(); + if ( updateValue< double >( d, names::dendritic_delay, dendritic_delay ) ) + { + set_dendritic_delay_ms( dendritic_delay ); + } + double axonal_delay = get_axonal_delay_ms(); + if ( updateValue< double >( d, names::axonal_delay, axonal_delay ) ) + { + set_axonal_delay_ms( axonal_delay ); + } + + kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( get_delay_ms() ); + } +}; + +//! check legal size +using success_axonal_dendritic_delay_data_size = StaticAssert< sizeof( AxonalDendriticDelay ) == 4 >::success; + +} + +#endif diff --git a/nestkernel/event.cpp b/nestkernel/event.cpp index 6d33a5f615..ec3ee12f24 100644 --- a/nestkernel/event.cpp +++ b/nestkernel/event.cpp @@ -73,6 +73,12 @@ SpikeEvent::operator()() receiver_->handle( *this ); } +void +CorrectionSpikeEvent::operator()() +{ + receiver_->handle( *this ); +} + void WeightRecorderEvent::operator()() { diff --git a/nestkernel/event.h b/nestkernel/event.h index 13860bd88a..dee2ef9c9f 100644 --- a/nestkernel/event.h +++ b/nestkernel/event.h @@ -322,6 +322,12 @@ class Event */ void set_stamp( Time const& ); + /** + * Returns the sender_spike_data_ + * The sender_spike_data_ is a SpikeData object + */ + SpikeData get_sender_spike_data() const; + protected: size_t sender_node_id_; //!< node ID of sender or 0 SpikeData sender_spike_data_; //!< spike data of sender node, in some cases required to retrieve node ID @@ -443,6 +449,43 @@ SpikeEvent::get_multiplicity() const return multiplicity_; } +class CorrectionSpikeEvent : public SpikeEvent +{ +public: + CorrectionSpikeEvent(); + void operator()() override; + CorrectionSpikeEvent* clone() const override; + + void set_new_weight( double ); + double get_new_weight() const; + +protected: + double new_weight_; +}; + +inline CorrectionSpikeEvent::CorrectionSpikeEvent() + : new_weight_( 0. ) +{ +} + +inline CorrectionSpikeEvent* +CorrectionSpikeEvent::clone() const +{ + return new CorrectionSpikeEvent( *this ); +} + +inline void +CorrectionSpikeEvent::set_new_weight( double new_weight ) +{ + new_weight_ = new_weight; +} + +inline double +CorrectionSpikeEvent::get_new_weight() const +{ + return new_weight_; +} + /** * Event for recording the weight of a spike. @@ -1031,6 +1074,12 @@ Event::set_rport( size_t rp ) { rp_ = rp; } + +inline SpikeData +Event::get_sender_spike_data() const +{ + return sender_spike_data_; +} } #endif /* EVENT_H */ diff --git a/nestkernel/event_delivery_manager.cpp b/nestkernel/event_delivery_manager.cpp index 8ba790b740..ca65d63970 100644 --- a/nestkernel/event_delivery_manager.cpp +++ b/nestkernel/event_delivery_manager.cpp @@ -663,7 +663,6 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik tid_batch[ j ] = spike_data.get_tid(); syn_id_batch[ j ] = spike_data.get_syn_id(); lcid_batch[ j ] = spike_data.get_lcid(); - se_batch[ j ].set_sender_node_id_info( tid_batch[ j ], syn_id_batch[ j ], lcid_batch[ j ] ); } for ( size_t j = 0; j < SPIKES_PER_BATCH; ++j ) { @@ -684,7 +683,6 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik tid_batch[ j ] = spike_data.get_tid(); syn_id_batch[ j ] = spike_data.get_syn_id(); lcid_batch[ j ] = spike_data.get_lcid(); - se_batch[ j ].set_sender_node_id_info( tid_batch[ j ], syn_id_batch[ j ], lcid_batch[ j ] ); } for ( size_t j = 0; j < num_remaining_entries; ++j ) { @@ -718,15 +716,6 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik lcid_batch[ j ] = compressed_spike_data[ tid ].get_lcid(); } for ( size_t j = 0; j < SPIKES_PER_BATCH; ++j ) - { - if ( lcid_batch[ j ] != invalid_lcid ) - { - // non-local sender -> receiver retrieves ID of sender Node from SourceTable based on tid, syn_id, lcid - // only if needed, as this is computationally costly - se_batch[ j ].set_sender_node_id_info( tid, syn_id_batch[ j ], lcid_batch[ j ] ); - } - } - for ( size_t j = 0; j < SPIKES_PER_BATCH; ++j ) { if ( lcid_batch[ j ] != invalid_lcid ) { @@ -755,15 +744,6 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik lcid_batch[ j ] = compressed_spike_data[ tid ].get_lcid(); } for ( size_t j = 0; j < num_remaining_entries; ++j ) - { - if ( lcid_batch[ j ] != invalid_lcid ) - { - // non-local sender -> receiver retrieves ID of sender Node from SourceTable based on tid, syn_id, lcid - // only if needed, as this is computationally costly - se_batch[ j ].set_sender_node_id_info( tid, syn_id_batch[ j ], lcid_batch[ j ] ); - } - } - for ( size_t j = 0; j < num_remaining_entries; ++j ) { if ( lcid_batch[ j ] != invalid_lcid ) { diff --git a/nestkernel/event_delivery_manager.h b/nestkernel/event_delivery_manager.h index dbdbe1483b..bf99e3d24b 100644 --- a/nestkernel/event_delivery_manager.h +++ b/nestkernel/event_delivery_manager.h @@ -314,22 +314,18 @@ class EventDeliveryManager : public ManagerInterface /** - * Reads spikes from MPI buffers and delivers them to ringbuffer of - * nodes. + * Reads spikes from MPI buffers and delivers them to ringbuffer of nodes. */ template < typename SpikeDataT > void deliver_events_( const size_t tid, const std::vector< SpikeDataT >& recv_buffer ); /** - * Deletes all spikes from spike registers and resets spike - * counters. + * Deletes all spikes from spike registers and resets spike counters. */ void reset_spike_register_( const size_t tid ); /** - * Returns true if spike has been moved to MPI buffer, such that it - * can be removed by clean_spike_register. Required static function - * by std::remove_if. + * Resizes spike registers according minimal delay so it can accommodate all possible lags. */ static bool is_marked_for_removal_( const Target& target ); @@ -347,22 +343,19 @@ class EventDeliveryManager : public ManagerInterface TargetSendBufferPosition& send_buffer_position ); /** - * Sets marker in MPI buffer that signals end of communication - * across MPI ranks. + * Sets marker in MPI buffer that signals end of communication across MPI ranks. */ void set_complete_marker_target_data_( const AssignedRanks& assigned_ranks, const TargetSendBufferPosition& send_buffer_position ); /** - * Reads TargetData objects from MPI buffers and creates Target - * objects on TargetTable (presynaptic part of connection - * infrastructure). + * Reads TargetData objects from MPI buffers and creates Target objects on TargetTable (presynaptic part of + * connection infrastructure). */ bool distribute_target_data_buffers_( const size_t tid ); /** - * Sends event e to all targets of node source. Delivers events from - * devices directly to targets. + * Sends event e to all targets of node source. Delivers events from devices directly to targets. */ template < class EventT > void send_local_( Node& source, EventT& e, const long lag ); @@ -370,8 +363,7 @@ class EventDeliveryManager : public ManagerInterface //--------------------------------------------------// - bool off_grid_spiking_; //!< indicates whether spikes are not constrained to - //!< the grid + bool off_grid_spiking_; //!< indicates whether spikes are not constrained to the grid /** * Table of pre-computed modulos. diff --git a/nestkernel/model_manager.cpp b/nestkernel/model_manager.cpp index a656285f13..2bdd50260b 100644 --- a/nestkernel/model_manager.cpp +++ b/nestkernel/model_manager.cpp @@ -476,4 +476,11 @@ ModelManager::create_proxynode_( size_t t, int model_id ) return proxy; } +void +ModelManager::check_valid_default_delay_parameters( const synindex syn_id, DictionaryDatum syn_params ) +{ + get_connection_model( syn_id, kernel().vp_manager.get_thread_id() ) + .check_valid_default_delay_parameters( syn_params ); +} + } // namespace nest diff --git a/nestkernel/model_manager.h b/nestkernel/model_manager.h index 924535a780..71efd20f06 100644 --- a/nestkernel/model_manager.h +++ b/nestkernel/model_manager.h @@ -114,7 +114,7 @@ class ModelManager : public ManagerInterface * * @param name The name under which the ConnectorModel will be registered. */ - template < template < typename targetidentifierT > class ConnectionT > + template < template < typename > class ConnectionT > void register_connection_model( const std::string& name ); /** @@ -176,6 +176,8 @@ class ModelManager : public ManagerInterface SecondaryEvent& get_secondary_event_prototype( const synindex syn_id, const size_t tid ); + void check_valid_default_delay_parameters( const synindex syn_id, DictionaryDatum syn_params ); + private: /** * Delete all models and clear the modeldict @@ -190,7 +192,7 @@ class ModelManager : public ManagerInterface size_t register_node_model_( Model* model ); - template < typename CompleteConnecionT > + template < typename CompleteConnectionT > void register_specific_connection_model_( const std::string& name ); /** diff --git a/nestkernel/nest.cpp b/nestkernel/nest.cpp index 2add49bcb6..33db13f202 100644 --- a/nestkernel/nest.cpp +++ b/nestkernel/nest.cpp @@ -198,12 +198,15 @@ connect_arrays( long* sources, long* targets, double* weights, double* delays, + double* dendritic_delay, + double* axonal_delays, std::vector< std::string >& p_keys, double* p_values, size_t n, std::string syn_model ) { - kernel().connection_manager.connect_arrays( sources, targets, weights, delays, p_keys, p_values, n, syn_model ); + kernel().connection_manager.connect_arrays( + sources, targets, weights, delays, dendritic_delay, axonal_delays, p_keys, p_values, n, syn_model ); } ArrayDatum diff --git a/nestkernel/nest.h b/nestkernel/nest.h index e49c7dcb5e..3525956031 100644 --- a/nestkernel/nest.h +++ b/nestkernel/nest.h @@ -123,6 +123,8 @@ void connect_arrays( long* sources, long* targets, double* weights, double* delays, + double* dendritic_delays, + double* axonal_delays, std::vector< std::string >& p_keys, double* p_values, size_t n, diff --git a/nestkernel/nest_names.cpp b/nestkernel/nest_names.cpp index 2b1d98435e..25cb92a8d3 100644 --- a/nestkernel/nest_names.cpp +++ b/nestkernel/nest_names.cpp @@ -75,6 +75,7 @@ const Name asc_init( "asc_init" ); const Name asc_r( "asc_r" ); const Name available( "available" ); const Name average_gradient( "average_gradient" ); +const Name axonal_delay( "axonal_delay" ); const Name azimuth_angle( "azimuth_angle" ); const Name b( "b" ); @@ -134,6 +135,7 @@ const Name delta_IP3( "delta_IP3" ); const Name delta_P( "delta_P" ); const Name delta_tau( "delta_tau" ); const Name dendritic_curr( "dendritic_curr" ); +const Name dendritic_delay( "dendritic_delay" ); const Name dendritic_exc( "dendritic_exc" ); const Name dendritic_inh( "dendritic_inh" ); const Name dg( "dg" ); @@ -356,6 +358,7 @@ const Name node_uses_wfr( "node_uses_wfr" ); const Name noise( "noise" ); const Name noisy_rate( "noisy_rate" ); const Name num_connections( "num_connections" ); +const Name num_corrections( "num_corrections" ); const Name num_processes( "num_processes" ); const Name number_of_connections( "number_of_connections" ); diff --git a/nestkernel/nest_names.h b/nestkernel/nest_names.h index 44a75f62d0..34e6c84009 100644 --- a/nestkernel/nest_names.h +++ b/nestkernel/nest_names.h @@ -101,6 +101,7 @@ extern const Name asc_init; extern const Name asc_r; extern const Name available; extern const Name average_gradient; +extern const Name axonal_delay; extern const Name azimuth_angle; extern const Name b; @@ -161,6 +162,7 @@ extern const Name delta_IP3; extern const Name delta_P; extern const Name delta_tau; extern const Name dendritic_curr; +extern const Name dendritic_delay; extern const Name dendritic_exc; extern const Name dendritic_inh; extern const Name dg; @@ -384,6 +386,7 @@ extern const Name node_uses_wfr; extern const Name noise; extern const Name noisy_rate; extern const Name num_connections; +extern const Name num_corrections; extern const Name num_processes; extern const Name number_of_connections; diff --git a/nestkernel/nest_time.cpp b/nestkernel/nest_time.cpp index 93b7e6f79f..35dd29af84 100644 --- a/nestkernel/nest_time.cpp +++ b/nestkernel/nest_time.cpp @@ -36,6 +36,9 @@ #include "integerdatum.h" #include "token.h" +// Includes from nestkernel: +#include "exceptions.h" + using namespace nest; const double Time::Range::TICS_PER_MS_DEFAULT = CONFIG_TICS_PER_MS; @@ -205,3 +208,23 @@ operator<<( std::ostream& strm, const Time& t ) return strm; } + +double +Time::delay_steps_to_ms( long steps ) +{ + if ( steps < 0 ) + { + throw BadDelay( steps * Range::MS_PER_STEP, "Delay value must be greater than or equal to zero." ); + } + return steps * Range::MS_PER_STEP; +} + +long +Time::delay_ms_to_steps( double ms ) +{ + if ( ms < 0 ) + { + throw BadDelay( ms, "Delay value must be greater than or equal to zero." ); + } + return ld_round( ms * Range::STEPS_PER_MS ); +} diff --git a/nestkernel/nest_time.h b/nestkernel/nest_time.h index f579af5659..56237965bb 100644 --- a/nestkernel/nest_time.h +++ b/nestkernel/nest_time.h @@ -535,17 +535,9 @@ class Time * ld_round, which is different from ms_stamp --> Time mapping, which rounds * up. See #903. */ - static double - delay_steps_to_ms( long steps ) - { - return steps * Range::MS_PER_STEP; - } + static double delay_steps_to_ms( long steps ); - static long - delay_ms_to_steps( double ms ) - { - return ld_round( ms * Range::STEPS_PER_MS ); - } + static long delay_ms_to_steps( double ms ); }; ///////////////////////////////////////////////////////////// diff --git a/nestkernel/node.cpp b/nestkernel/node.cpp index 6f54cc1075..3de045f0e1 100644 --- a/nestkernel/node.cpp +++ b/nestkernel/node.cpp @@ -143,6 +143,12 @@ Node::get_local_device_id() const return invalid_index; } +void +Node::add_correction_entry_stdp_ax_delay( SpikeEvent&, const double, const double, const double ) +{ + throw UnexpectedEvent( "Node does not support framework for STDP synapses with predominantly axonal delays." ); +} + DictionaryDatum Node::get_status_base() { @@ -204,7 +210,7 @@ size_t Node::send_test_event( Node&, size_t, synindex, bool ) { throw IllegalConnection( - "Source node does not send output.\n" + "Source node does not send output." " Note that recorders must be connected as Connect(neuron, recorder)." ); } @@ -213,7 +219,7 @@ Node::send_test_event( Node&, size_t, synindex, bool ) * throws IllegalConnection */ void -Node::register_stdp_connection( double, double ) +Node::register_stdp_connection( double, double, double ) { throw IllegalConnection( "The target node does not support STDP synapses." ); } @@ -259,12 +265,25 @@ Node::handle( SpikeEvent& ) { throw UnexpectedEvent( "The target node does not handle spike input." ); } +void +Node::handle( CorrectionSpikeEvent& ) +{ + throw UnexpectedEvent( "The target node does not handle spike input." ); +} size_t Node::handles_test_event( SpikeEvent&, size_t ) { throw IllegalConnection( - "The target node or synapse model does not support spike input.\n" + "The target node or synapse model does not support spike input." + " Note that volt/multimeters must be connected as Connect(meter, neuron)." ); +} + +size_t +Node::handles_test_event( CorrectionSpikeEvent&, size_t ) +{ + throw IllegalConnection( + "The target node or synapse model does not support spike input with axonal delays." " Note that volt/multimeters must be connected as Connect(meter, neuron)." ); } diff --git a/nestkernel/node.h b/nestkernel/node.h index 5c41113f43..90ca9aef9b 100644 --- a/nestkernel/node.h +++ b/nestkernel/node.h @@ -400,6 +400,7 @@ class Node * @throws IllegalConnection */ virtual size_t handles_test_event( SpikeEvent&, size_t receptor_type ); + virtual size_t handles_test_event( CorrectionSpikeEvent&, size_t receptor_type ); virtual size_t handles_test_event( WeightRecorderEvent&, size_t receptor_type ); virtual size_t handles_test_event( RateEvent&, size_t receptor_type ); virtual size_t handles_test_event( DataLoggingRequest&, size_t receptor_type ); @@ -481,7 +482,7 @@ class Node * @throws IllegalConnection * */ - virtual void register_stdp_connection( double, double ); + virtual void register_stdp_connection( double, double, double ); /** * @brief Registers an eprop synapse and initializes the update history. @@ -557,6 +558,7 @@ class Node * @ingroup event_interface */ virtual void handle( SpikeEvent& e ); + virtual void handle( CorrectionSpikeEvent& ); /** * Handle incoming weight recording events. @@ -1010,6 +1012,21 @@ class Node */ virtual size_t get_local_device_id() const; + /** + * Framework for STDP with predominantly axonal delays: Buffer a correction entry for a short time window. + * + * @param spike_event Incoming pre-synaptic spike which could potentially need a correction after the next + * post-synaptic spike. + * @param t_last_pre_spike The time of the last pre-synaptic spike that was processed before the current one. + * @param weight_revert The synaptic weight before depression after facilitation as baseline for potential later + * correction. + * @param time_while_critical The number of time steps until the spike no longer needs to be corrected. + */ + void add_correction_entry_stdp_ax_delay( SpikeEvent& spike_event, + const double t_last_pre_spike, + const double weight_revert, + const double time_while_critical ); + /** * Member of DeprecationWarning class to be used by models if parameters are * deprecated. diff --git a/nestkernel/node_manager.cpp b/nestkernel/node_manager.cpp index ca5f28ed98..974ade9031 100644 --- a/nestkernel/node_manager.cpp +++ b/nestkernel/node_manager.cpp @@ -619,8 +619,7 @@ NodeManager::set_status_single_node_( Node& target, const DictionaryDatum& d, bo } target.set_status_base( d ); - // TODO: Not sure this check should be at single neuron level; advantage is - // it stops after first failure. + // TODO: Not sure this check should be at single neuron level; advantage is it stops after first failure. ALL_ENTRIES_ACCESSED( *d, "NodeManager::set_status", "Unread dictionary entries: " ); } } diff --git a/nestkernel/recording_backend_ascii.cpp b/nestkernel/recording_backend_ascii.cpp index 773aa36a82..bfafc150ac 100644 --- a/nestkernel/recording_backend_ascii.cpp +++ b/nestkernel/recording_backend_ascii.cpp @@ -32,31 +32,34 @@ #include "recording_backend_ascii.h" -const unsigned int nest::RecordingBackendASCII::ASCII_REC_BACKEND_VERSION = 2; +namespace nest +{ + +const unsigned int RecordingBackendASCII::ASCII_REC_BACKEND_VERSION = 2; -nest::RecordingBackendASCII::RecordingBackendASCII() +RecordingBackendASCII::RecordingBackendASCII() { } -nest::RecordingBackendASCII::~RecordingBackendASCII() throw() +RecordingBackendASCII::~RecordingBackendASCII() throw() { } void -nest::RecordingBackendASCII::initialize() +RecordingBackendASCII::initialize() { data_map tmp( kernel().vp_manager.get_num_threads() ); device_data_.swap( tmp ); } void -nest::RecordingBackendASCII::finalize() +RecordingBackendASCII::finalize() { // nothing to do } void -nest::RecordingBackendASCII::enroll( const RecordingDevice& device, const DictionaryDatum& params ) +RecordingBackendASCII::enroll( const RecordingDevice& device, const DictionaryDatum& params ) { const size_t t = device.get_thread(); const size_t node_id = device.get_node_id(); @@ -74,7 +77,7 @@ nest::RecordingBackendASCII::enroll( const RecordingDevice& device, const Dictio } void -nest::RecordingBackendASCII::disenroll( const RecordingDevice& device ) +RecordingBackendASCII::disenroll( const RecordingDevice& device ) { const size_t t = device.get_thread(); const size_t node_id = device.get_node_id(); @@ -87,7 +90,7 @@ nest::RecordingBackendASCII::disenroll( const RecordingDevice& device ) } void -nest::RecordingBackendASCII::set_value_names( const RecordingDevice& device, +RecordingBackendASCII::set_value_names( const RecordingDevice& device, const std::vector< Name >& double_value_names, const std::vector< Name >& long_value_names ) { @@ -100,13 +103,13 @@ nest::RecordingBackendASCII::set_value_names( const RecordingDevice& device, } void -nest::RecordingBackendASCII::pre_run_hook() +RecordingBackendASCII::pre_run_hook() { // nothing to do } void -nest::RecordingBackendASCII::post_run_hook() +RecordingBackendASCII::post_run_hook() { for ( auto& inner : device_data_ ) { @@ -118,13 +121,13 @@ nest::RecordingBackendASCII::post_run_hook() } void -nest::RecordingBackendASCII::post_step_hook() +RecordingBackendASCII::post_step_hook() { // nothing to do } void -nest::RecordingBackendASCII::cleanup() +RecordingBackendASCII::cleanup() { for ( auto& inner : device_data_ ) { @@ -136,7 +139,7 @@ nest::RecordingBackendASCII::cleanup() } void -nest::RecordingBackendASCII::write( const RecordingDevice& device, +RecordingBackendASCII::write( const RecordingDevice& device, const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) @@ -154,7 +157,7 @@ nest::RecordingBackendASCII::write( const RecordingDevice& device, } const std::string -nest::RecordingBackendASCII::compute_vp_node_id_string_( const RecordingDevice& device ) const +RecordingBackendASCII::compute_vp_node_id_string_( const RecordingDevice& device ) const { const double num_vps = kernel().vp_manager.get_num_virtual_processes(); const double num_nodes = kernel().node_manager.size(); @@ -169,7 +172,7 @@ nest::RecordingBackendASCII::compute_vp_node_id_string_( const RecordingDevice& } void -nest::RecordingBackendASCII::prepare() +RecordingBackendASCII::prepare() { for ( auto& inner : device_data_ ) { @@ -181,33 +184,33 @@ nest::RecordingBackendASCII::prepare() } void -nest::RecordingBackendASCII::set_status( const DictionaryDatum& ) +RecordingBackendASCII::set_status( const DictionaryDatum& ) { // nothing to do } void -nest::RecordingBackendASCII::get_status( DictionaryDatum& ) const +RecordingBackendASCII::get_status( DictionaryDatum& ) const { // nothing to do } void -nest::RecordingBackendASCII::check_device_status( const DictionaryDatum& params ) const +RecordingBackendASCII::check_device_status( const DictionaryDatum& params ) const { DeviceData dd( "", "" ); dd.set_status( params ); // throws if params contains invalid entries } void -nest::RecordingBackendASCII::get_device_defaults( DictionaryDatum& params ) const +RecordingBackendASCII::get_device_defaults( DictionaryDatum& params ) const { DeviceData dd( "", "" ); dd.get_status( params ); } void -nest::RecordingBackendASCII::get_device_status( const nest::RecordingDevice& device, DictionaryDatum& d ) const +RecordingBackendASCII::get_device_status( const RecordingDevice& device, DictionaryDatum& d ) const { const size_t t = device.get_thread(); const size_t node_id = device.get_node_id(); @@ -221,7 +224,7 @@ nest::RecordingBackendASCII::get_device_status( const nest::RecordingDevice& dev /* ******************* Device meta data class DeviceData ******************* */ -nest::RecordingBackendASCII::DeviceData::DeviceData( std::string modelname, std::string vp_node_id_string ) +RecordingBackendASCII::DeviceData::DeviceData( std::string modelname, std::string vp_node_id_string ) : precision_( 3 ) , time_in_steps_( false ) , modelname_( modelname ) @@ -232,7 +235,7 @@ nest::RecordingBackendASCII::DeviceData::DeviceData( std::string modelname, std: } void -nest::RecordingBackendASCII::DeviceData::set_value_names( const std::vector< Name >& double_value_names, +RecordingBackendASCII::DeviceData::set_value_names( const std::vector< Name >& double_value_names, const std::vector< Name >& long_value_names ) { double_value_names_ = double_value_names; @@ -240,13 +243,13 @@ nest::RecordingBackendASCII::DeviceData::set_value_names( const std::vector< Nam } void -nest::RecordingBackendASCII::DeviceData::flush_file() +RecordingBackendASCII::DeviceData::flush_file() { file_.flush(); } void -nest::RecordingBackendASCII::DeviceData::open_file() +RecordingBackendASCII::DeviceData::open_file() { std::string filename = compute_filename_(); @@ -289,13 +292,13 @@ nest::RecordingBackendASCII::DeviceData::open_file() } void -nest::RecordingBackendASCII::DeviceData::close_file() +RecordingBackendASCII::DeviceData::close_file() { file_.close(); } void -nest::RecordingBackendASCII::DeviceData::write( const Event& event, +RecordingBackendASCII::DeviceData::write( const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) { @@ -323,7 +326,7 @@ nest::RecordingBackendASCII::DeviceData::write( const Event& event, } void -nest::RecordingBackendASCII::DeviceData::get_status( DictionaryDatum& d ) const +RecordingBackendASCII::DeviceData::get_status( DictionaryDatum& d ) const { ( *d )[ names::file_extension ] = file_extension_; ( *d )[ names::precision ] = precision_; @@ -335,7 +338,7 @@ nest::RecordingBackendASCII::DeviceData::get_status( DictionaryDatum& d ) const } void -nest::RecordingBackendASCII::DeviceData::set_status( const DictionaryDatum& d ) +RecordingBackendASCII::DeviceData::set_status( const DictionaryDatum& d ) { updateValue< std::string >( d, names::file_extension, file_extension_ ); updateValue< long >( d, names::precision, precision_ ); @@ -354,7 +357,7 @@ nest::RecordingBackendASCII::DeviceData::set_status( const DictionaryDatum& d ) } std::string -nest::RecordingBackendASCII::DeviceData::compute_filename_() const +RecordingBackendASCII::DeviceData::compute_filename_() const { std::string data_path = kernel().io_manager.get_data_path(); if ( not data_path.empty() and not( data_path[ data_path.size() - 1 ] == '/' ) ) @@ -372,3 +375,5 @@ nest::RecordingBackendASCII::DeviceData::compute_filename_() const return data_path + data_prefix + label + vp_node_id_string_ + "." + file_extension_; } + +} // namespace nest \ No newline at end of file diff --git a/nestkernel/recording_backend_memory.cpp b/nestkernel/recording_backend_memory.cpp index 3ff816c685..b98b8adce0 100644 --- a/nestkernel/recording_backend_memory.cpp +++ b/nestkernel/recording_backend_memory.cpp @@ -26,28 +26,31 @@ #include "recording_backend_memory.h" -nest::RecordingBackendMemory::RecordingBackendMemory() +namespace nest +{ + +RecordingBackendMemory::RecordingBackendMemory() { } -nest::RecordingBackendMemory::~RecordingBackendMemory() throw() +RecordingBackendMemory::~RecordingBackendMemory() throw() { } void -nest::RecordingBackendMemory::initialize() +RecordingBackendMemory::initialize() { device_data_map tmp( kernel().vp_manager.get_num_threads() ); device_data_.swap( tmp ); } void -nest::RecordingBackendMemory::finalize() +RecordingBackendMemory::finalize() { } void -nest::RecordingBackendMemory::enroll( const RecordingDevice& device, const DictionaryDatum& params ) +RecordingBackendMemory::enroll( const RecordingDevice& device, const DictionaryDatum& params ) { size_t t = device.get_thread(); size_t node_id = device.get_node_id(); @@ -63,7 +66,7 @@ nest::RecordingBackendMemory::enroll( const RecordingDevice& device, const Dicti } void -nest::RecordingBackendMemory::disenroll( const RecordingDevice& device ) +RecordingBackendMemory::disenroll( const RecordingDevice& device ) { size_t t = device.get_thread(); size_t node_id = device.get_node_id(); @@ -76,7 +79,7 @@ nest::RecordingBackendMemory::disenroll( const RecordingDevice& device ) } void -nest::RecordingBackendMemory::set_value_names( const RecordingDevice& device, +RecordingBackendMemory::set_value_names( const RecordingDevice& device, const std::vector< Name >& double_value_names, const std::vector< Name >& long_value_names ) { @@ -89,19 +92,19 @@ nest::RecordingBackendMemory::set_value_names( const RecordingDevice& device, } void -nest::RecordingBackendMemory::pre_run_hook() +RecordingBackendMemory::pre_run_hook() { // nothing to do } void -nest::RecordingBackendMemory::cleanup() +RecordingBackendMemory::cleanup() { // nothing to do } void -nest::RecordingBackendMemory::write( const RecordingDevice& device, +RecordingBackendMemory::write( const RecordingDevice& device, const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) @@ -113,21 +116,21 @@ nest::RecordingBackendMemory::write( const RecordingDevice& device, } void -nest::RecordingBackendMemory::check_device_status( const DictionaryDatum& params ) const +RecordingBackendMemory::check_device_status( const DictionaryDatum& params ) const { DeviceData dd; dd.set_status( params ); // throws if params contains invalid entries } void -nest::RecordingBackendMemory::get_device_defaults( DictionaryDatum& params ) const +RecordingBackendMemory::get_device_defaults( DictionaryDatum& params ) const { DeviceData dd; dd.get_status( params ); } void -nest::RecordingBackendMemory::get_device_status( const RecordingDevice& device, DictionaryDatum& d ) const +RecordingBackendMemory::get_device_status( const RecordingDevice& device, DictionaryDatum& d ) const { const size_t t = device.get_thread(); const size_t node_id = device.get_node_id(); @@ -140,44 +143,44 @@ nest::RecordingBackendMemory::get_device_status( const RecordingDevice& device, } void -nest::RecordingBackendMemory::post_run_hook() +RecordingBackendMemory::post_run_hook() { // nothing to do } void -nest::RecordingBackendMemory::post_step_hook() +RecordingBackendMemory::post_step_hook() { // nothing to do } void -nest::RecordingBackendMemory::get_status( lockPTRDatum< Dictionary, &SLIInterpreter::Dictionarytype >& ) const +RecordingBackendMemory::get_status( lockPTRDatum< Dictionary, &SLIInterpreter::Dictionarytype >& ) const { // nothing to do } void -nest::RecordingBackendMemory::set_status( lockPTRDatum< Dictionary, &SLIInterpreter::Dictionarytype > const& ) +RecordingBackendMemory::set_status( lockPTRDatum< Dictionary, &SLIInterpreter::Dictionarytype > const& ) { // nothing to do } void -nest::RecordingBackendMemory::prepare() +RecordingBackendMemory::prepare() { // nothing to do } /* ******************* Device meta data class DeviceInfo ******************* */ -nest::RecordingBackendMemory::DeviceData::DeviceData() +RecordingBackendMemory::DeviceData::DeviceData() : time_in_steps_( false ) { } void -nest::RecordingBackendMemory::DeviceData::set_value_names( const std::vector< Name >& double_value_names, +RecordingBackendMemory::DeviceData::set_value_names( const std::vector< Name >& double_value_names, const std::vector< Name >& long_value_names ) { double_value_names_ = double_value_names; @@ -188,7 +191,7 @@ nest::RecordingBackendMemory::DeviceData::set_value_names( const std::vector< Na } void -nest::RecordingBackendMemory::DeviceData::push_back( const Event& event, +RecordingBackendMemory::DeviceData::push_back( const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) { @@ -215,7 +218,7 @@ nest::RecordingBackendMemory::DeviceData::push_back( const Event& event, } void -nest::RecordingBackendMemory::DeviceData::get_status( DictionaryDatum& d ) const +RecordingBackendMemory::DeviceData::get_status( DictionaryDatum& d ) const { DictionaryDatum events; @@ -261,7 +264,7 @@ nest::RecordingBackendMemory::DeviceData::get_status( DictionaryDatum& d ) const } void -nest::RecordingBackendMemory::DeviceData::set_status( const DictionaryDatum& d ) +RecordingBackendMemory::DeviceData::set_status( const DictionaryDatum& d ) { bool time_in_steps = false; if ( updateValue< bool >( d, names::time_in_steps, time_in_steps ) ) @@ -282,7 +285,7 @@ nest::RecordingBackendMemory::DeviceData::set_status( const DictionaryDatum& d ) } void -nest::RecordingBackendMemory::DeviceData::clear() +RecordingBackendMemory::DeviceData::clear() { senders_.clear(); times_ms_.clear(); @@ -298,3 +301,5 @@ nest::RecordingBackendMemory::DeviceData::clear() long_values_[ i ].clear(); } } + +} // namespace nest \ No newline at end of file diff --git a/nestkernel/recording_backend_mpi.cpp b/nestkernel/recording_backend_mpi.cpp index 3c048211a0..ddcede1043 100644 --- a/nestkernel/recording_backend_mpi.cpp +++ b/nestkernel/recording_backend_mpi.cpp @@ -29,6 +29,9 @@ #include "recording_backend_mpi.h" #include "recording_device.h" +namespace nest +{ + nest::RecordingBackendMPI::RecordingBackendMPI() : enrolled_( false ) , prepared_( false ) @@ -423,3 +426,5 @@ nest::RecordingBackendMPI::send_data( const MPI_Comm* comm, const double data[], // Receive the data ( for the moment only spike time ) MPI_Send( data, shape, MPI_DOUBLE, 0, 0, *comm ); } + +} // namespace nest \ No newline at end of file diff --git a/nestkernel/recording_backend_screen.cpp b/nestkernel/recording_backend_screen.cpp index 9b31ea6f57..21065f483e 100644 --- a/nestkernel/recording_backend_screen.cpp +++ b/nestkernel/recording_backend_screen.cpp @@ -28,20 +28,23 @@ #include "recording_backend_screen.h" +namespace nest +{ + void -nest::RecordingBackendScreen::initialize() +RecordingBackendScreen::initialize() { device_data_map tmp( kernel().vp_manager.get_num_threads() ); device_data_.swap( tmp ); } void -nest::RecordingBackendScreen::finalize() +RecordingBackendScreen::finalize() { } void -nest::RecordingBackendScreen::enroll( const RecordingDevice& device, const DictionaryDatum& params ) +RecordingBackendScreen::enroll( const RecordingDevice& device, const DictionaryDatum& params ) { const size_t node_id = device.get_node_id(); const size_t t = device.get_thread(); @@ -57,7 +60,7 @@ nest::RecordingBackendScreen::enroll( const RecordingDevice& device, const Dicti } void -nest::RecordingBackendScreen::disenroll( const RecordingDevice& device ) +RecordingBackendScreen::disenroll( const RecordingDevice& device ) { const size_t node_id = device.get_node_id(); const size_t t = device.get_thread(); @@ -70,7 +73,7 @@ nest::RecordingBackendScreen::disenroll( const RecordingDevice& device ) } void -nest::RecordingBackendScreen::set_value_names( const RecordingDevice&, +RecordingBackendScreen::set_value_names( const RecordingDevice&, const std::vector< Name >&, const std::vector< Name >& ) { @@ -78,19 +81,19 @@ nest::RecordingBackendScreen::set_value_names( const RecordingDevice&, } void -nest::RecordingBackendScreen::pre_run_hook() +RecordingBackendScreen::pre_run_hook() { // nothing to do } void -nest::RecordingBackendScreen::cleanup() +RecordingBackendScreen::cleanup() { // nothing to do } void -nest::RecordingBackendScreen::write( const RecordingDevice& device, +RecordingBackendScreen::write( const RecordingDevice& device, const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) @@ -107,21 +110,21 @@ nest::RecordingBackendScreen::write( const RecordingDevice& device, } void -nest::RecordingBackendScreen::check_device_status( const DictionaryDatum& params ) const +RecordingBackendScreen::check_device_status( const DictionaryDatum& params ) const { DeviceData dd; dd.set_status( params ); // throws if params contains invalid entries } void -nest::RecordingBackendScreen::get_device_defaults( DictionaryDatum& params ) const +RecordingBackendScreen::get_device_defaults( DictionaryDatum& params ) const { DeviceData dd; dd.get_status( params ); } void -nest::RecordingBackendScreen::get_device_status( const nest::RecordingDevice& device, DictionaryDatum& d ) const +RecordingBackendScreen::get_device_status( const RecordingDevice& device, DictionaryDatum& d ) const { const size_t t = device.get_thread(); const size_t node_id = device.get_node_id(); @@ -135,59 +138,59 @@ nest::RecordingBackendScreen::get_device_status( const nest::RecordingDevice& de void -nest::RecordingBackendScreen::prepare() +RecordingBackendScreen::prepare() { // nothing to do } void -nest::RecordingBackendScreen::post_run_hook() +RecordingBackendScreen::post_run_hook() { // nothing to do } void -nest::RecordingBackendScreen::post_step_hook() +RecordingBackendScreen::post_step_hook() { // nothing to do } void -nest::RecordingBackendScreen::set_status( const DictionaryDatum& ) +RecordingBackendScreen::set_status( const DictionaryDatum& ) { // nothing to do } void -nest::RecordingBackendScreen::get_status( DictionaryDatum& ) const +RecordingBackendScreen::get_status( DictionaryDatum& ) const { // nothing to do } /* ******************* Device meta data class DeviceInfo ******************* */ -nest::RecordingBackendScreen::DeviceData::DeviceData() +RecordingBackendScreen::DeviceData::DeviceData() : precision_( 3 ) , time_in_steps_( false ) { } void -nest::RecordingBackendScreen::DeviceData::get_status( DictionaryDatum& d ) const +RecordingBackendScreen::DeviceData::get_status( DictionaryDatum& d ) const { ( *d )[ names::precision ] = precision_; ( *d )[ names::time_in_steps ] = time_in_steps_; } void -nest::RecordingBackendScreen::DeviceData::set_status( const DictionaryDatum& d ) +RecordingBackendScreen::DeviceData::set_status( const DictionaryDatum& d ) { updateValue< long >( d, names::precision, precision_ ); updateValue< bool >( d, names::time_in_steps, time_in_steps_ ); } void -nest::RecordingBackendScreen::DeviceData::write( const Event& event, +RecordingBackendScreen::DeviceData::write( const Event& event, const std::vector< double >& double_values, const std::vector< long >& long_values ) { @@ -221,15 +224,17 @@ nest::RecordingBackendScreen::DeviceData::write( const Event& event, } void -nest::RecordingBackendScreen::DeviceData::prepare_cout_() +RecordingBackendScreen::DeviceData::prepare_cout_() { old_fmtflags_ = std::cout.flags( std::ios::fixed ); old_precision_ = std::cout.precision( precision_ ); } void -nest::RecordingBackendScreen::DeviceData::restore_cout_() +RecordingBackendScreen::DeviceData::restore_cout_() { std::cout.flags( old_fmtflags_ ); std::cout.precision( old_precision_ ); } + +} \ No newline at end of file diff --git a/nestkernel/recording_backend_sionlib.cpp b/nestkernel/recording_backend_sionlib.cpp index 5aabb26ebc..517b0c9249 100644 --- a/nestkernel/recording_backend_sionlib.cpp +++ b/nestkernel/recording_backend_sionlib.cpp @@ -41,6 +41,9 @@ #include "recording_backend_sionlib.h" +namespace nest +{ + const unsigned int nest::RecordingBackendSIONlib::SIONLIB_REC_BACKEND_VERSION = 2; const unsigned int nest::RecordingBackendSIONlib::DEV_NAME_BUFFERSIZE = 32; const unsigned int nest::RecordingBackendSIONlib::DEV_LABEL_BUFFERSIZE = 32; @@ -703,3 +706,5 @@ nest::RecordingBackendSIONlib::get_device_status( const nest::RecordingDevice&, { // nothing to do } + +} // namespace nest \ No newline at end of file diff --git a/nestkernel/simulation_manager.cpp b/nestkernel/simulation_manager.cpp index 9f23d7f89b..ad5dde3d61 100644 --- a/nestkernel/simulation_manager.cpp +++ b/nestkernel/simulation_manager.cpp @@ -34,7 +34,6 @@ #include "numerics.h" // Includes from nestkernel: -#include "connection_manager_impl.h" #include "event_delivery_manager.h" #include "kernel_manager.h" #include "stopwatch_impl.h" @@ -539,11 +538,25 @@ nest::SimulationManager::prepare() } prepared_ = true; - // check whether waveform relaxation is used on any MPI process; - // needs to be called before update_connection_intrastructure_since - // it resizes coefficient arrays for secondary events + // check whether waveform relaxation is used on any MPI process; needs to be called before + // update_connection_infrastructure() since it resizes coefficient arrays for secondary events kernel().node_manager.check_wfr_use(); + // If we simulated already and we use axonal delays, we have to make sure connectivity didn't change, as this would + // invalidate the correction entries in the neurons that are required for connections with predominant axonal delays. + if ( simulated_ and kernel().connection_manager.have_nonzero_axonal_delays() + and kernel().connection_manager.connections_have_changed() ) + { + throw KernelException( + "Connections have changed during simulation, which is not allowed when using axonal delays!" ); + } + + if ( kernel().connection_manager.have_nonzero_axonal_delays() + and kernel().sp_manager.is_structural_plasticity_enabled() ) + { + throw KernelException( "Structural plasticity is not compatible with axonal delays!" ); + } + if ( kernel().node_manager.have_nodes_changed() or kernel().connection_manager.connections_have_changed() ) { #pragma omp parallel @@ -909,7 +922,7 @@ nest::SimulationManager::update_() #endif } // if from_step == 0 - // preliminary update of nodes that use waveform relaxtion, only + // preliminary update of nodes that use waveform relaxation, only // necessary if secondary connections exist and any node uses // wfr if ( kernel().connection_manager.secondary_connections_exist() and kernel().node_manager.wfr_is_used() ) diff --git a/nestkernel/sonata_connector.cpp b/nestkernel/sonata_connector.cpp index b44ae89640..4e9420a149 100644 --- a/nestkernel/sonata_connector.cpp +++ b/nestkernel/sonata_connector.cpp @@ -476,6 +476,8 @@ SonataConnector::connect_chunk_( const hsize_t hyperslab_size, const hsize_t off edge_type_id_2_syn_model_.at( edge_type_id ), edge_type_id_2_param_dicts_.at( edge_type_id ).at( tid ), delay, + numerics::nan, + numerics::nan, weight ); } // end for diff --git a/nestkernel/sp_manager.cpp b/nestkernel/sp_manager.cpp index 4705b7de64..d9b039573b 100644 --- a/nestkernel/sp_manager.cpp +++ b/nestkernel/sp_manager.cpp @@ -156,8 +156,8 @@ SPManager::set_status( const DictionaryDatum& d ) SPBuilder* conn_builder = new SPBuilder( sources, targets, /* third_out */ nullptr, conn_spec, { syn_spec } ); conn_builder->set_name( i->first.toString() ); - // check that the user defined the min and max delay properly, if the - // default delay is not used. + // TODO: Consider axonal delays here + // check that the user defined the min and max delay properly, if the default delay is not used. if ( not conn_builder->get_default_delay() and not kernel().connection_manager.get_user_set_delay_extrema() ) { throw BadProperty( @@ -171,6 +171,7 @@ SPManager::set_status( const DictionaryDatum& d ) long SPManager::builder_min_delay() const { + // TODO: Consider axonal delays here long min_delay = Time::pos_inf().get_steps(); long builder_delay = Time::pos_inf().get_steps(); @@ -185,6 +186,7 @@ SPManager::builder_min_delay() const long SPManager::builder_max_delay() const { + // TODO: Consider axonal delays here long max_delay = Time::neg_inf().get_steps(); long builder_delay = Time::neg_inf().get_steps(); diff --git a/nestkernel/spike_data.h b/nestkernel/spike_data.h index 87b1205ba0..d2271f4372 100644 --- a/nestkernel/spike_data.h +++ b/nestkernel/spike_data.h @@ -86,8 +86,7 @@ enum enum_status_spike_data_id }; /** - * Used to communicate spikes. These are the elements of the MPI - * buffers. + * Used to communicate spikes. These are the elements of the MPI buffers. * * @see TargetData */ diff --git a/nestkernel/stimulation_device.cpp b/nestkernel/stimulation_device.cpp index ab3c800c9b..de7bbaca7f 100644 --- a/nestkernel/stimulation_device.cpp +++ b/nestkernel/stimulation_device.cpp @@ -25,8 +25,10 @@ #include "stimulation_device.h" #include "kernel_manager.h" +namespace nest +{ -nest::StimulationDevice::StimulationDevice() +StimulationDevice::StimulationDevice() : DeviceNode() , Device() , first_syn_id_( invalid_synindex ) @@ -34,7 +36,7 @@ nest::StimulationDevice::StimulationDevice() { } -nest::StimulationDevice::StimulationDevice( StimulationDevice const& sd ) +StimulationDevice::StimulationDevice( StimulationDevice const& sd ) : DeviceNode( sd ) , Device( sd ) , P_( sd.P_ ) @@ -44,7 +46,7 @@ nest::StimulationDevice::StimulationDevice( StimulationDevice const& sd ) } bool -nest::StimulationDevice::is_active( const Time& T ) const +StimulationDevice::is_active( const Time& T ) const { long step = T.get_steps(); if ( get_type() == StimulationDevice::Type::CURRENT_GENERATOR @@ -57,7 +59,7 @@ nest::StimulationDevice::is_active( const Time& T ) const } void -nest::StimulationDevice::enforce_single_syn_type( synindex syn_id ) +StimulationDevice::enforce_single_syn_type( synindex syn_id ) { if ( first_syn_id_ == invalid_synindex ) { @@ -70,39 +72,39 @@ nest::StimulationDevice::enforce_single_syn_type( synindex syn_id ) } void -nest::StimulationDevice::pre_run_hook() +StimulationDevice::pre_run_hook() { Device::pre_run_hook(); } void -nest::StimulationDevice::set_initialized_() +StimulationDevice::set_initialized_() { kernel().io_manager.enroll_stimulator( P_.stimulus_source_, *this, backend_params_ ); } const std::string& -nest::StimulationDevice::get_label() const +StimulationDevice::get_label() const { return P_.label_; } -nest::StimulationDevice::Parameters_::Parameters_() +StimulationDevice::Parameters_::Parameters_() : label_() , stimulus_source_( Name() ) { } void -nest::StimulationDevice::Parameters_::get( DictionaryDatum& d ) const +StimulationDevice::Parameters_::get( DictionaryDatum& d ) const { ( *d )[ names::label ] = label_; ( *d )[ names::stimulus_source ] = LiteralDatum( stimulus_source_ ); } void -nest::StimulationDevice::Parameters_::set( const DictionaryDatum& d ) +StimulationDevice::Parameters_::set( const DictionaryDatum& d ) { updateValue< std::string >( d, names::label, label_ ); @@ -120,7 +122,7 @@ nest::StimulationDevice::Parameters_::set( const DictionaryDatum& d ) } void -nest::StimulationDevice::set_status( const DictionaryDatum& d ) +StimulationDevice::set_status( const DictionaryDatum& d ) { Parameters_ ptmp = P_; // temporary copy in case of errors @@ -163,7 +165,7 @@ nest::StimulationDevice::set_status( const DictionaryDatum& d ) void -nest::StimulationDevice::get_status( DictionaryDatum& d ) const +StimulationDevice::get_status( DictionaryDatum& d ) const { P_.get( d ); @@ -180,3 +182,5 @@ nest::StimulationDevice::get_status( DictionaryDatum& d ) const } } } + +} // namespace nest \ No newline at end of file diff --git a/nestkernel/structural_plasticity_node.cpp b/nestkernel/structural_plasticity_node.cpp index 07a3af88e4..b46c7b5334 100644 --- a/nestkernel/structural_plasticity_node.cpp +++ b/nestkernel/structural_plasticity_node.cpp @@ -31,7 +31,7 @@ namespace nest { -nest::StructuralPlasticityNode::StructuralPlasticityNode() +StructuralPlasticityNode::StructuralPlasticityNode() : Ca_t_( 0.0 ) , Ca_minus_( 0.0 ) , tau_Ca_( 10000.0 ) @@ -40,7 +40,7 @@ nest::StructuralPlasticityNode::StructuralPlasticityNode() { } -nest::StructuralPlasticityNode::StructuralPlasticityNode( const StructuralPlasticityNode& n ) +StructuralPlasticityNode::StructuralPlasticityNode( const StructuralPlasticityNode& n ) : Node( n ) , Ca_t_( n.Ca_t_ ) , Ca_minus_( n.Ca_minus_ ) @@ -51,7 +51,7 @@ nest::StructuralPlasticityNode::StructuralPlasticityNode( const StructuralPlasti } void -nest::StructuralPlasticityNode::get_status( DictionaryDatum& d ) const +StructuralPlasticityNode::get_status( DictionaryDatum& d ) const { DictionaryDatum synaptic_elements_d; DictionaryDatum synaptic_element_d; @@ -73,7 +73,7 @@ nest::StructuralPlasticityNode::get_status( DictionaryDatum& d ) const } void -nest::StructuralPlasticityNode::set_status( const DictionaryDatum& d ) +StructuralPlasticityNode::set_status( const DictionaryDatum& d ) { // We need to preserve values in case invalid values are set double new_Ca_ = Ca_minus_; @@ -145,14 +145,14 @@ nest::StructuralPlasticityNode::set_status( const DictionaryDatum& d ) } void -nest::StructuralPlasticityNode::clear_history() +StructuralPlasticityNode::clear_history() { Ca_minus_ = 0.0; Ca_t_ = 0.0; } double -nest::StructuralPlasticityNode::get_synaptic_elements( Name n ) const +StructuralPlasticityNode::get_synaptic_elements( Name n ) const { std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); @@ -177,7 +177,7 @@ nest::StructuralPlasticityNode::get_synaptic_elements( Name n ) const } int -nest::StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const +StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const { std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); @@ -193,7 +193,7 @@ nest::StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const } int -nest::StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const +StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const { std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); @@ -209,7 +209,7 @@ nest::StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const } std::map< Name, double > -nest::StructuralPlasticityNode::get_synaptic_elements() const +StructuralPlasticityNode::get_synaptic_elements() const { std::map< Name, double > n_map; @@ -223,7 +223,7 @@ nest::StructuralPlasticityNode::get_synaptic_elements() const } void -nest::StructuralPlasticityNode::update_synaptic_elements( double t ) +StructuralPlasticityNode::update_synaptic_elements( double t ) { assert( t >= Ca_t_ ); @@ -239,7 +239,7 @@ nest::StructuralPlasticityNode::update_synaptic_elements( double t ) } void -nest::StructuralPlasticityNode::decay_synaptic_elements_vacant() +StructuralPlasticityNode::decay_synaptic_elements_vacant() { for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); @@ -250,7 +250,7 @@ nest::StructuralPlasticityNode::decay_synaptic_elements_vacant() } void -nest::StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) +StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) { std::map< Name, SynapticElement >::iterator se_it; se_it = synaptic_elements_map_.find( name ); @@ -262,7 +262,7 @@ nest::StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) } void -nest::StructuralPlasticityNode::set_spiketime( Time const& t_sp, double offset ) +StructuralPlasticityNode::set_spiketime( Time const& t_sp, double offset ) { const double t_sp_ms = t_sp.get_ms() - offset; update_synaptic_elements( t_sp_ms ); diff --git a/nestkernel/structural_plasticity_node.h b/nestkernel/structural_plasticity_node.h index ffaf0c9f67..d545d255d2 100644 --- a/nestkernel/structural_plasticity_node.h +++ b/nestkernel/structural_plasticity_node.h @@ -72,8 +72,7 @@ class StructuralPlasticityNode : public Node int get_synaptic_elements_vacant( Name n ) const override; /** - * Get the number of synaptic element of type n which are currently - * connected + * Get the number of synaptic element of type n which are currently connected */ int get_synaptic_elements_connected( Name n ) const override; @@ -89,8 +88,7 @@ class StructuralPlasticityNode : public Node void update_synaptic_elements( double t ) override; /** - * Delete a certain portion of the vacant synaptic elements which are not - * in use + * Delete a certain portion of the vacant synaptic elements which are not in use */ void decay_synaptic_elements_vacant() override; diff --git a/nestkernel/syn_id_delay.h b/nestkernel/syn_id_delay.h deleted file mode 100644 index c3693137ce..0000000000 --- a/nestkernel/syn_id_delay.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * syn_id_delay.h - * - * This file is part of NEST. - * - * Copyright (C) 2004 The NEST Initiative - * - * NEST is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * NEST is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with NEST. If not, see . - * - */ - -#ifndef SYN_ID_DELAY_H -#define SYN_ID_DELAY_H - -// Includes from nestkernel: -#include "nest_time.h" -#include "nest_types.h" - -namespace nest -{ - -struct SynIdDelay -{ - unsigned int delay : NUM_BITS_DELAY; - unsigned int syn_id : NUM_BITS_SYN_ID; - bool more_targets : 1; - bool disabled : 1; - - explicit SynIdDelay( double d ) - : syn_id( invalid_synindex ) - , more_targets( false ) - , disabled( false ) - { - set_delay_ms( d ); - } - - SynIdDelay( const SynIdDelay& s ) = default; - SynIdDelay& operator=( const SynIdDelay& s ) = default; - - /** - * Return the delay of the connection in ms - */ - double - get_delay_ms() const - { - return Time::delay_steps_to_ms( delay ); - } - - /** - * Set the delay of the connection specified in ms - */ - void - set_delay_ms( const double d ) - { - delay = Time::delay_ms_to_steps( d ); - } - - void - set_source_has_more_targets( const bool more_targets ) - { - this->more_targets = more_targets; - } - - bool - source_has_more_targets() const - { - return more_targets; - } - - /** - * Disables the synapse. - * - * @see is_disabled - */ - void - disable() - { - disabled = true; - } - - /** - * Returns a flag denoting if the synapse is disabled. - * - * @see disable - */ - bool - is_disabled() const - { - return disabled; - } -}; - -//! check legal size -using success_syn_id_delay_data_size = StaticAssert< sizeof( SynIdDelay ) == 4 >::success; -} - -#endif diff --git a/nestkernel/target_table_devices_impl.h b/nestkernel/target_table_devices_impl.h index 26a4668fb1..28a64834ec 100644 --- a/nestkernel/target_table_devices_impl.h +++ b/nestkernel/target_table_devices_impl.h @@ -47,7 +47,7 @@ nest::TargetTableDevices::add_connection_to_device( Node& source, kernel() .model_manager.get_connection_model( syn_id, tid ) - .add_connection( source, target, target_to_devices_[ tid ][ lid ], syn_id, p, d, w ); + .add_connection( source, target, target_to_devices_[ tid ][ lid ], syn_id, p, d, numerics::nan, numerics::nan, w ); } inline void @@ -66,7 +66,8 @@ nest::TargetTableDevices::add_connection_from_device( Node& source, kernel() .model_manager.get_connection_model( syn_id, tid ) - .add_connection( source, target, target_from_devices_[ tid ][ ldid ], syn_id, p, d, w ); + .add_connection( + source, target, target_from_devices_[ tid ][ ldid ], syn_id, p, d, numerics::nan, numerics::nan, w ); // store node ID of sending device sending_devices_node_ids_[ tid ][ ldid ] = source.get_node_id(); diff --git a/pynest/examples/axonal_delays.py b/pynest/examples/axonal_delays.py new file mode 100644 index 0000000000..7eb8fba4ec --- /dev/null +++ b/pynest/examples/axonal_delays.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +# +# axonal_delays.py +# +# This file is part of NEST. +# +# Copyright (C) 2004 The NEST Initiative +# +# NEST is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# NEST is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with NEST. If not, see . + +""" +Example of using axonal delays in NEST +-------------------------------------- + +This script demonstrates the use of axonal delays, by comparing neuronal simulations with +and without axonal delays (i.e., only dendritic delays). It analyzes the impact of axonal delays +on synaptic weight distributions using the Jensen-Shannon divergence +and the number of corrections required for different fractions of axonal delays. +It uses the synapse model ``stdp_pl_synapse_hom_ax_delay``, which supports the +use of axonal delays. + +For more information see :ref:`delays`. +""" + + +######################################## +# First, we import all necessary modules + +import os.path + +import matplotlib.pyplot as plt +import nest +import numpy as np +import seaborn as sns +from scipy.spatial.distance import jensenshannon + +######################################## +# Next we set the parameters + + +tau_syn = 0.32582722403722841 +neuron_params = { + "E_L": 0.0, + "C_m": 250.0, + "tau_m": 10.0, + "t_ref": 0.5, + "V_th": 20.0, + "V_reset": 0.0, + "tau_syn_ex": tau_syn, + "tau_syn_in": tau_syn, + "tau_minus": 30.0, + "V_m": 5.7, +} + +stdp_params = {"alpha": 0.0513, "mu": 0.4, "tau_plus": 15.0, "weight": 45.0} + +NE = 9000 +eta = 4.92 + +single_column_in = 3.348 + + +################################################################################# +# And then we set up the simulation + + +def run(T, axonal_delay, dendritic_delay, enable_stdp, use_ax_delay): + # Enable or disable STDP + if enable_stdp: + stdp_params["lambda"] = 1.0 + else: + stdp_params["lambda"] = 0.0 + # Reset the NEST kernel and set simulation parameters + nest.ResetKernel() + nest.local_num_threads = 8 + nest.resolution = 0.1 + nest.rng_seed = 42 + nest.set_verbosity("M_ERROR") + + # Create devices and neurons + E_ext = nest.Create("poisson_generator", 1, {"rate": eta * 1000.0}) + E_pg = nest.Create("poisson_generator", 1, params={"rate": 10.0}) + I_pg = nest.Create("poisson_generator", 1, params={"rate": 10.0 * NE / 5}) + E_neurons = nest.Create("parrot_neuron", NE) + I_neurons = nest.Create("parrot_neuron", 1) + post_neuron = nest.Create("iaf_psc_alpha", 1, params=neuron_params) + sr = nest.Create("spike_recorder") + + # Set synapse parameters with axonal and dendritic delays + syn_params_copy = stdp_params.copy() + if use_ax_delay: + syn_params_copy["dendritic_delay"] = dendritic_delay + syn_params_copy["axonal_delay"] = axonal_delay + # Use the new synapse model with axonal delays + syn_model = "stdp_pl_synapse_hom_ax_delay" + else: + syn_params_copy["delay"] = dendritic_delay + axonal_delay + syn_model = "stdp_pl_synapse_hom" + + nest.SetDefaults(syn_model, syn_params_copy) + + # Connect neurons and devices + nest.Connect(E_pg, E_neurons) + nest.Connect(I_pg, I_neurons) + nest.Connect(E_neurons, post_neuron, syn_spec={"synapse_model": syn_model}) + nest.Connect(I_neurons, post_neuron, syn_spec={"weight": 45.0 * -5}) + nest.Connect(E_ext, post_neuron, syn_spec={"weight": 45.0}) + nest.Connect(post_neuron, sr) + + # Run the simulation + nest.Simulate(T) + + return sr, post_neuron + + +##################################################################### +# Set the font sizes for graph + + +def set_font_sizes(small=8, medium=10, large=12, family="Arial"): + # plt.rc('text', usetex=True) + plt.rc("font", size=small) # controls default text sizes + plt.rc("axes", titlesize=small) # fontsize of the axes title + plt.rc("axes", labelsize=medium) # fontsize of the x and y labels + plt.rc("xtick", labelsize=small) # fontsize of the tick labels + plt.rc("ytick", labelsize=small) # fontsize of the tick labels + plt.rc("legend", fontsize=small) # legend fontsize + plt.rc("figure", titlesize=large) # fontsize of the figure title + plt.rc("font", family=family) + + +##################################################################### +# Measure the similarity between two probability distributions using +# Jensen-Shannon divergence + + +def jensen_shannon_divergence(weights_correction, weights_no_correction): + p = np.histogram(weights_correction, bins=100000, density=True)[0] + q = np.histogram(weights_no_correction, bins=100000, density=True)[0] + return round(jensenshannon(p, q) ** 2, 3) + + +#################################################################################### +# Get different weight distributions of purely dendritic and axonal+dendritic delays + + +_, post_neuron = run(10000.0, 5.0, 0.0, enable_stdp=True, use_ax_delay=True) +weights_correction = nest.GetConnections(target=post_neuron, synapse_model="stdp_pl_synapse_hom_ax_delay").get("weight") +_, post_neuron = run(10000.0, 5.0, 0.0, enable_stdp=True, use_ax_delay=False) +weights_no_correction = nest.GetConnections(target=post_neuron, synapse_model="stdp_pl_synapse_hom").get("weight") + +print( + "Jensen-Shannon divergence of weight distributions:", + jensen_shannon_divergence(weights_correction, weights_no_correction), +) + +######################################################################### +# Plot the weight distributions + +fig, ax = plt.subplots(figsize=(single_column_in, 3.5)) +set_font_sizes() +sns.distplot( + weights_correction, + hist=False, + kde=True, + kde_kws={"fill": True, "linewidth": 3}, + label="axonal delay and correction", + ax=ax, +) +sns.distplot( + weights_no_correction, + hist=False, + kde=True, + kde_kws={"fill": True, "linewidth": 3}, + label="purely dendritic delay", + ax=ax, +) +plt.setp(ax.spines.values(), linewidth=2) +ax.set_xlabel("Synaptic weight [pA]") +ax.tick_params(width=2) +plt.legend() +fig.tight_layout() +plt.show() + + +######################################################################### +# Measure number of corrections for increasing fractions of axonal delays + + +ax_perc = np.arange(0.0, 1.01, 0.01, dtype=np.float32) +num_corrections = np.empty(101, dtype=np.int32) +for i, p in enumerate(ax_perc): + run(500.0, 5.0 * p, 5.0 * (1 - p), enable_stdp=False, use_ax_delay=True) + num_corrections[i] = nest.kernel_status["num_corrections"] + +########################################################################## +# Plot the number of corrections + +fig, ax = plt.subplots(figsize=(single_column_in, 3.5)) +set_font_sizes() +plt.plot(ax_perc, num_corrections, color="black") +plt.setp(ax.spines.values(), linewidth=2) +ax.set_xlabel("Fraction of axonal delay") +ax.set_ylabel("Number of corrections") # average per neuron +ax.tick_params(width=2) +fig.tight_layout() +plt.show() diff --git a/pynest/nest/lib/hl_api_connection_helpers.py b/pynest/nest/lib/hl_api_connection_helpers.py index e9fe89b7be..c8cc47baf9 100644 --- a/pynest/nest/lib/hl_api_connection_helpers.py +++ b/pynest/nest/lib/hl_api_connection_helpers.py @@ -173,7 +173,15 @@ def _process_spatial_projections(conn_spec, syn_spec): "use_on_source", "allow_oversized_mask", ] - allowed_syn_spec_keys = ["weight", "delay", "synapse_model", "synapse_label", "receptor_type"] + allowed_syn_spec_keys = [ + "weight", + "delay", + "dendritic_delay", + "axonal_delay", + "synapse_model", + "synapse_label", + "receptor_type", + ] for key in conn_spec.keys(): if key not in allowed_conn_spec_keys: raise ValueError("'{}' is not allowed in conn_spec when connecting with mask or kernel".format(key)) diff --git a/pynest/nest/lib/hl_api_connections.py b/pynest/nest/lib/hl_api_connections.py index aef9dd0674..e1c902af65 100644 --- a/pynest/nest/lib/hl_api_connections.py +++ b/pynest/nest/lib/hl_api_connections.py @@ -232,9 +232,19 @@ def Connect(pre, post, conn_spec=None, syn_spec=None, return_synapsecollection=F raise ValueError("To specify weights, use 'weight' in syn_spec.") if "delays" in processed_syn_spec: raise ValueError("To specify delays, use 'delay' in syn_spec.") + if "dendritic_delays" in processed_syn_spec: + raise ValueError("To specify dendritic delays, use 'dendritic_delay' in syn_spec.") + if "axonal_delays" in processed_syn_spec: + raise ValueError("To specify axonal delays, use 'axonal_delay' in syn_spec.") weights = numpy.array(processed_syn_spec["weight"]) if "weight" in processed_syn_spec else None delays = numpy.array(processed_syn_spec["delay"]) if "delay" in processed_syn_spec else None + dendritic_delays = ( + numpy.array(processed_syn_spec["dendritic_delay"]) if "dendritic_delay" in processed_syn_spec else None + ) + axonal_delays = ( + numpy.array(processed_syn_spec["axonal_delay"]) if "axonal_delay" in processed_syn_spec else None + ) try: synapse_model = processed_syn_spec["synapse_model"] @@ -247,7 +257,9 @@ def Connect(pre, post, conn_spec=None, syn_spec=None, return_synapsecollection=F # Split remaining syn_spec entries to key and value arrays reduced_processed_syn_spec = { k: processed_syn_spec[k] - for k in set(processed_syn_spec.keys()).difference(set(("weight", "delay", "synapse_model"))) + for k in set(processed_syn_spec.keys()).difference( + set(("weight", "delay", "axonal_delay", "synapse_model")) + ) } if len(reduced_processed_syn_spec) > 0: @@ -257,7 +269,17 @@ def Connect(pre, post, conn_spec=None, syn_spec=None, return_synapsecollection=F else: syn_param_values = None - connect_arrays(pre, post, weights, delays, synapse_model, reduced_processed_syn_spec.keys(), syn_param_values) + connect_arrays( + pre, + post, + weights, + delays, + dendritic_delays, + axonal_delays, + synapse_model, + reduced_processed_syn_spec.keys(), + syn_param_values, + ) return diff --git a/pynest/pynestkernel.pxd b/pynest/pynestkernel.pxd index 7a766f4696..36391166fb 100644 --- a/pynest/pynestkernel.pxd +++ b/pynest/pynestkernel.pxd @@ -148,7 +148,7 @@ cdef extern from "neststartup.h": cdef extern from "nest.h" namespace "nest": Datum* node_collection_array_index(const Datum* node_collection, const long* array, unsigned long n) except + Datum* node_collection_array_index(const Datum* node_collection, const cbool* array, unsigned long n) except + - void connect_arrays( long* sources, long* targets, double* weights, double* delays, vector[string]& p_keys, double* p_values, size_t n, string syn_model ) except + + void connect_arrays( long* sources, long* targets, double* weights, double* delays, double* dendritic_delays, double* axonal_delays, vector[string]& p_keys, double* p_values, size_t n, string syn_model ) except + cdef extern from *: diff --git a/pynest/pynestkernel.pyx b/pynest/pynestkernel.pyx index 1fdf7fa537..97446de66e 100644 --- a/pynest/pynestkernel.pyx +++ b/pynest/pynestkernel.pyx @@ -281,7 +281,7 @@ cdef class NESTEngine: exceptionCls = getattr(NESTErrors, str(e)) raise exceptionCls('take_array_index', '') from None - def connect_arrays(self, sources, targets, weights, delays, synapse_model, syn_param_keys, syn_param_values): + def connect_arrays(self, sources, targets, weights, delays, dendritic_delays, axonal_delays, synapse_model, syn_param_keys, syn_param_values): """Calls connect_arrays function, bypassing SLI to expose pointers to the NumPy arrays""" if self.pEngine is NULL: raise NESTErrors.PyNESTError("engine uninitialized") @@ -296,6 +296,8 @@ cdef class NESTEngine: raise TypeError('weights must be a 1-dimensional NumPy array') if delays is not None and not (isinstance(delays, numpy.ndarray) and delays.ndim == 1): raise TypeError('delays must be a 1-dimensional NumPy array') + if axonal_delays is not None and not (isinstance(axonal_delays, numpy.ndarray) and axonal_delays.ndim == 1): + raise TypeError('axonal_delays must be a 1-dimensional NumPy array') if syn_param_values is not None and not ((isinstance(syn_param_values, numpy.ndarray) and syn_param_values.ndim == 2)): raise TypeError('syn_param_values must be a 2-dimensional NumPy array') @@ -305,6 +307,9 @@ cdef class NESTEngine: raise ValueError('weights must be an array of the same length as sources and targets.') if delays is not None and len(sources) != len(delays): raise ValueError('delays must be an array of the same length as sources and targets.') + if axonal_delays is not None: + if not len(sources) == len(axonal_delays): + raise ValueError('axonal_delays must be an array of the same length as sources and targets.') if syn_param_values is not None: if not len(syn_param_keys) == syn_param_values.shape[0]: raise ValueError('syn_param_values must be a matrix with one array per key in syn_param_keys.') @@ -330,6 +335,18 @@ cdef class NESTEngine: delays_mv = numpy.ascontiguousarray(delays, dtype=numpy.double) delays_ptr = &delays_mv[0] + cdef double[::1] dendritic_delays_mv + cdef double* dendritic_delays_ptr = NULL + if dendritic_delays is not None: + dendritic_delays_mv = numpy.ascontiguousarray(dendritic_delays, dtype=numpy.double) + dendritic_delays_ptr = &dendritic_delays_mv[0] + + cdef double[::1] axonal_delays_mv + cdef double* axonal_delays_ptr = NULL + if axonal_delays is not None: + axonal_delays_mv = numpy.ascontiguousarray(axonal_delays, dtype=numpy.double) + axonal_delays_ptr = &axonal_delays_mv[0] + # Storing parameter keys in a vector of strings cdef vector[string] param_keys_ptr if syn_param_keys is not None: @@ -345,7 +362,7 @@ cdef class NESTEngine: cdef string syn_model_string = synapse_model.encode('UTF-8') try: - connect_arrays( sources_ptr, targets_ptr, weights_ptr, delays_ptr, param_keys_ptr, param_values_ptr, len(sources), syn_model_string ) + connect_arrays( sources_ptr, targets_ptr, weights_ptr, delays_ptr, dendritic_delays_ptr, axonal_delays_ptr, param_keys_ptr, param_values_ptr, len(sources), syn_model_string ) except RuntimeError as e: exceptionCls = getattr(NESTErrors, str(e)) raise exceptionCls('connect_arrays', '') from None diff --git a/sli/dictstack.h b/sli/dictstack.h index e4b05e0118..ca8d957fc1 100644 --- a/sli/dictstack.h +++ b/sli/dictstack.h @@ -144,7 +144,7 @@ class DictionaryStack /** Clear the entire cache. - * This should be called whenever a dictionary is pushed or poped. + * This should be called whenever a dictionary is pushed or popped. * Alternative, one could just clear the names from the moved dictionary. */ void diff --git a/testsuite/pytests/connect_test_base.py b/testsuite/pytests/connect_test_base.py index 12124080ba..0643313116 100644 --- a/testsuite/pytests/connect_test_base.py +++ b/testsuite/pytests/connect_test_base.py @@ -63,8 +63,7 @@ class ConnectTestBase(unittest.TestCase): # number of threads nr_threads = 2 - # for now only tests if a multi-thread connect is successful, not whether - # the the threading is actually used + # for now only tests if a multi-thread connect is successful, not whether the threading is actually used def setUp(self): nest.ResetKernel() nest.local_num_threads = self.nr_threads diff --git a/testsuite/pytests/sli2py_connect/test_gap_junction.py b/testsuite/pytests/sli2py_connect/test_gap_junction.py index dcc94d7893..8ec5f00e3f 100644 --- a/testsuite/pytests/sli2py_connect/test_gap_junction.py +++ b/testsuite/pytests/sli2py_connect/test_gap_junction.py @@ -72,7 +72,7 @@ def test_neuron_gap_connect_with_delay_fails(conn_spec): leads to an error. """ syn_spec = {"synapse_model": "gap_junction", "delay": 2.0} - with pytest.raises(nest.kernel.NESTError, match="gap_junction connection has no delay"): + with pytest.raises(nest.kernel.NESTError, match="Delay specified for a connection type which doesn't use delays."): nest.Connect(pytest.neuron_gap, pytest.neuron_gap, conn_spec=conn_spec, syn_spec=syn_spec) diff --git a/testsuite/pytests/sli2py_recording/test_compare_delta.py b/testsuite/pytests/sli2py_recording/test_compare_delta.py index 7af5f8f5ec..60b7eba672 100644 --- a/testsuite/pytests/sli2py_recording/test_compare_delta.py +++ b/testsuite/pytests/sli2py_recording/test_compare_delta.py @@ -63,5 +63,5 @@ def test_simulation_completes(): spike_recs = spike_recorder.get("events", ["senders", "times"]) - assert np.all(np.in1d(np.array([1, 2]), spike_recs["senders"].T[:2])) + assert np.all(np.isin(np.array([1, 2]), spike_recs["senders"].T[:2])) assert np.all(spike_recs["times"].T[:2] == pytest.approx(4.1)) diff --git a/testsuite/pytests/sli2py_regressions/test_ticket_941.py b/testsuite/pytests/sli2py_regressions/test_ticket_941.py index 7c8d33cd60..18aa71f450 100644 --- a/testsuite/pytests/sli2py_regressions/test_ticket_941.py +++ b/testsuite/pytests/sli2py_regressions/test_ticket_941.py @@ -95,4 +95,4 @@ def test_different_connections(): synapses = nest.GetConnections(source=pn1, target=pn2).get("synapse_model") expected_synapses = ["static_synapse", "static_synapse", "static_synapse_hom_w"] - assert np.all(np.in1d(expected_synapses, synapses)) + assert np.all(np.isin(expected_synapses, synapses)) diff --git a/testsuite/pytests/test_axonal_delay_connectivity_changed.py b/testsuite/pytests/test_axonal_delay_connectivity_changed.py new file mode 100644 index 0000000000..1dfdf8c9c2 --- /dev/null +++ b/testsuite/pytests/test_axonal_delay_connectivity_changed.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# +# test_axonal_delay_connectivity_changed.py +# +# This file is part of NEST. +# +# Copyright (C) 2004 The NEST Initiative +# +# NEST is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# NEST is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with NEST. If not, see . + +import nest +import pytest + + +@pytest.mark.parametrize("conn1, conn2", [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) +def test_axonal_delay_connectivity_changed(conn1, conn2): + """ + Test that changing connectivity during simulation throws an exception when using axonal delays. + """ + nest.ResetKernel() + + nest.SetKernelStatus({"min_delay": 1.0, "max_delay": 2.0}) + + neuron = nest.Create("iaf_psc_alpha") + + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "axonal_delay": conn1}) + + nest.Simulate(nest.resolution) + + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "axonal_delay": conn2}) + + if conn1 > 0.0 or conn2 > 0.0: + with pytest.raises(nest.kernel.NESTError): + nest.Simulate(nest.resolution) + else: + nest.Simulate(nest.resolution) diff --git a/testsuite/pytests/test_axonal_delay_user_interface.py b/testsuite/pytests/test_axonal_delay_user_interface.py new file mode 100644 index 0000000000..4a7ce7f8a4 --- /dev/null +++ b/testsuite/pytests/test_axonal_delay_user_interface.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- +# +# test_axonal_delay_user_interface.py +# +# This file is part of NEST. +# +# Copyright (C) 2004 The NEST Initiative +# +# NEST is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# NEST is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with NEST. If not, see . + +import nest +import pytest + + +def test_total_delay_user_interface_connect_success(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay in the Connect call. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom", "delay": 1.0}, return_synapsecollection=True + ) + assert nest.GetStatus(conn)[0]["delay"] == 1.0 + + +def test_total_delay_user_interface_set_status_success(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay when using SetStatus. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom"}, return_synapsecollection=True + ) + nest.SetStatus(conn, {"delay": 1.0}) + assert nest.GetStatus(conn)[0]["delay"] == 1.0 + + +def test_total_delay_user_interface_set_defaults_success(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay when using SetDefaults. + """ + nest.ResetKernel() + + nest.SetDefaults("stdp_pl_synapse_hom", {"delay": 1.0}) + assert nest.GetDefaults("stdp_pl_synapse_hom")["delay"] == 1.0 + + +@pytest.mark.parametrize("ax_delay, dend_delay", [[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) +def test_split_delay_user_interface_connect_success(ax_delay, dend_delay): + """ + Make sure that one can only set the axonal or dendritic delay for synapses which support split axonal and dendritic + delays and setting the total transmission delay via the "delay" parameter name must fail because of ambiguity. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, + neuron, + syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "axonal_delay": 1.0}, + return_synapsecollection=True, + ) + assert nest.GetStatus(conn)[0]["axonal_delay"] == 1.0 + conn = nest.Connect( + neuron, + neuron, + syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "dendritic_delay": 1.0}, + return_synapsecollection=True, + ) + assert nest.GetStatus(conn)[0]["dendritic_delay"] == 1.0 + + +@pytest.mark.parametrize("ax_delay, dend_delay", [[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) +def test_split_delay_user_interface_set_status_success(ax_delay, dend_delay): + """ + Make sure that one can only set the axonal or dendritic delay for synapses which support split axonal and dendritic + delays and setting the total transmission delay via the "delay" parameter name must fail because of ambiguity. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay"}, return_synapsecollection=True + ) + nest.SetStatus(conn, {"axonal_delay": 1.0}) + nest.SetStatus(conn, {"dendritic_delay": 1.0}) + assert nest.GetStatus(conn)[0]["axonal_delay"] == 1.0 + assert nest.GetStatus(conn)[0]["dendritic_delay"] == 1.0 + + +@pytest.mark.parametrize("ax_delay, dend_delay", [[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) +def test_split_delay_user_interface_set_defaults_success(ax_delay, dend_delay): + """ + Make sure that one can set the axonal or dendritic delay for synapses which support split axonal and dendritic + delays and setting the total transmission delay via the "delay" parameter name must fail because of ambiguity. + """ + nest.ResetKernel() + + nest.SetDefaults("stdp_pl_synapse_hom_ax_delay", {"axonal_delay": 1.0}) + nest.SetDefaults("stdp_pl_synapse_hom_ax_delay", {"dendritic_delay": 1.0}) + assert nest.GetDefaults("stdp_pl_synapse_hom_ax_delay")["axonal_delay"] == 1.0 + assert nest.GetDefaults("stdp_pl_synapse_hom_ax_delay")["dendritic_delay"] == 1.0 + + +def test_total_delay_user_interface_connect_failure(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay in the Connect call. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + with pytest.raises(nest.kernel.NESTError): + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom", "axonal_delay": 1.0}) + with pytest.raises(nest.kernel.NESTError): + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom", "dendritic_delay": 1.0}) + + +def test_total_delay_user_interface_set_status_failure(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay when using SetStatus. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom"}, return_synapsecollection=True + ) + with pytest.raises(nest.kernel.NESTError): + nest.SetStatus(conn, {"dendritic_delay": 1.0}) + with pytest.raises(nest.kernel.NESTError): + nest.SetStatus(conn, {"axonal_delay": 1.0}) + + +def test_total_delay_user_interface_set_defaults_failure(): + """ + Make sure that one can only set the total delay and not just the axonal or dendritic delay for synapses which only + support a total transmission delay when using SetDefaults. + """ + nest.ResetKernel() + + with pytest.raises(nest.kernel.NESTError): + nest.SetDefaults("stdp_pl_synapse_hom", {"axonal_delay": 1.0}) + with pytest.raises(nest.kernel.NESTError): + nest.SetDefaults("stdp_pl_synapse_hom", {"dendritic_delay": 1.0}) + + +def test_split_delay_user_interface_connect_failure(): + """ + Make sure that setting the total transmission delay via the "delay" parameter name in Connect fails because of + ambiguity. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + with pytest.raises(nest.kernel.NESTError): + nest.Connect(neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "delay": 1.0}) + + +def test_split_delay_user_interface_set_status_failure(): + """ + Make sure that setting the total transmission delay via the "delay" parameter name in SetStatus fails because of + ambiguity. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay"}, return_synapsecollection=True + ) + with pytest.raises(nest.kernel.NESTError): + nest.SetStatus(conn, {"delay": 1.0}) + + +def test_split_delay_user_interface_set_defaults_failure(): + """ + Make sure that setting the total transmission delay via the "delay" parameter name in SetDefaults fails because of + ambiguity. + """ + nest.ResetKernel() + + with pytest.raises(nest.kernel.NESTError): + nest.SetDefaults("stdp_pl_synapse_hom_ax_delay", {"delay": 1.0}) + + +def test_split_delay_user_interface_connect_zero_delay_failure(): + """ + Make sure that either the dendritic or axonal delay is non-zero. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + with pytest.raises(nest.kernel.NESTError): + nest.Connect( + neuron, + neuron, + syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay", "dendritic_delay": 0.0, "axonal_delay": 0.0}, + ) + + +def test_split_delay_user_interface_set_status_zero_delay_failure(): + """ + Make sure that either the dendritic or axonal delay is non-zero. + """ + nest.ResetKernel() + + neuron = nest.Create("iaf_psc_alpha") + + conn = nest.Connect( + neuron, neuron, syn_spec={"synapse_model": "stdp_pl_synapse_hom_ax_delay"}, return_synapsecollection=True + ) + with pytest.raises(nest.kernel.NESTError): + nest.SetStatus(conn, {"dendritic_delay": 0.0, "axonal_delay": 0.0}) + + +def test_split_delay_user_interface_set_defaults_zero_delay_failure(): + """ + Make sure that either the dendritic or axonal delay is non-zero. + """ + nest.ResetKernel() + + with pytest.raises(nest.kernel.NESTError): + nest.SetDefaults("stdp_pl_synapse_hom_ax_delay", {"dendritic_delay": 0.0, "axonal_delay": 0.0}) diff --git a/testsuite/pytests/test_labeled_synapses.py b/testsuite/pytests/test_labeled_synapses.py index 0ff60ceec7..ae0e430edb 100644 --- a/testsuite/pytests/test_labeled_synapses.py +++ b/testsuite/pytests/test_labeled_synapses.py @@ -55,6 +55,12 @@ def default_network(self, syn_model): self.clopath_synapses = ["clopath_synapse", "clopath_synapse_lbl", "clopath_synapse_hpc"] + self.axonal_delay_synapses = [ + "stdp_pl_synapse_hom_ax_delay", + "stdp_pl_synapse_hom_ax_delay_lbl", + "stdp_pl_synapse_hom_ax_delay_hpc", + ] + self.urbanczik_synapses = ["urbanczik_synapse", "urbanczik_synapse_lbl", "urbanczik_synapse_hpc"] self.eprop_synapses_bsshslm_2020 = ["eprop_synapse_bsshslm_2020", "eprop_synapse_bsshslm_2020_hpc"] @@ -88,6 +94,10 @@ def default_network(self, syn_model): if syn_model in self.clopath_synapses: neurons = nest.Create("hh_psc_alpha_clopath", 5) + # in case of synapses with axonal delays use a supported model instead + if syn_model in self.axonal_delay_synapses: + neurons = nest.Create("iaf_psc_alpha", 5) + r_type = 0 # in case of the urbanczik synapse use a supported model instead if syn_model in self.urbanczik_synapses: diff --git a/testsuite/pytests/test_sp/test_disconnect_multiple.py b/testsuite/pytests/test_sp/test_disconnect_multiple.py index a3eeebf0ed..95b313f5be 100644 --- a/testsuite/pytests/test_sp/test_disconnect_multiple.py +++ b/testsuite/pytests/test_sp/test_disconnect_multiple.py @@ -35,6 +35,10 @@ def setUp(self): "stdp_dopamine_synapse_lbl", "stdp_dopamine_synapse_hpc", "stdp_dopamine_synapse_hpc_lbl", + "stdp_pl_synapse_hom_ax_delay", + "stdp_pl_synapse_hom_ax_delay_lbl", + "stdp_pl_synapse_hom_ax_delay_hpc", + "stdp_pl_synapse_hom_ax_delay_hpc_lbl", "gap_junction", "gap_junction_lbl", "diffusion_connection", @@ -66,7 +70,6 @@ def test_multiple_synapse_deletion_all_to_all(self): for syn_model in nest.synapse_models: if syn_model not in self.exclude_synapse_model: nest.ResetKernel() - nest.CopyModel("static_synapse", "my_static_synapse") nest.SetDefaults(syn_model, {"delay": 0.5}) syn_dict = {"synapse_model": syn_model, "pre_synaptic_element": "SE1", "post_synaptic_element": "SE2"} # For co-dependent properties, we use `set()` instead of kernel attributes @@ -113,7 +116,6 @@ def test_multiple_synapse_deletion_one_to_one(self): for syn_model in nest.synapse_models: if syn_model not in self.exclude_synapse_model: nest.ResetKernel() - nest.CopyModel("static_synapse", "my_static_synapse") nest.SetDefaults(syn_model, {"delay": 0.5}) syn_dict = {"synapse_model": syn_model, "pre_synaptic_element": "SE1", "post_synaptic_element": "SE2"} # For co-dependent properties, we use `set()` instead of kernel attributes @@ -160,7 +162,6 @@ def test_multiple_synapse_deletion_one_to_one_no_sp(self): for syn_model in nest.synapse_models: if syn_model not in self.exclude_synapse_model: nest.ResetKernel() - nest.CopyModel("static_synapse", "my_static_synapse") neurons = nest.Create("iaf_psc_alpha", 10) syn_dict = {"synapse_model": syn_model} nest.Connect(neurons, neurons, "all_to_all", syn_dict) diff --git a/testsuite/pytests/test_sp/test_sp_manager.py b/testsuite/pytests/test_sp/test_sp_manager.py index 4631b613ab..f1334c37c9 100644 --- a/testsuite/pytests/test_sp/test_sp_manager.py +++ b/testsuite/pytests/test_sp/test_sp_manager.py @@ -39,6 +39,10 @@ def setUp(self): "stdp_dopamine_synapse_lbl", "stdp_dopamine_synapse_hpc", "stdp_dopamine_synapse_hpc_lbl", + "stdp_pl_synapse_hom_ax_delay", + "stdp_pl_synapse_hom_ax_delay_lbl", + "stdp_pl_synapse_hom_ax_delay_hpc", + "stdp_pl_synapse_hom_ax_delay_hpc_lbl", "gap_junction", "gap_junction_lbl", "diffusion_connection", diff --git a/testsuite/pytests/test_spatial/test_axonal_delay.py b/testsuite/pytests/test_spatial/test_axonal_delay.py new file mode 100644 index 0000000000..ee7c9cad16 --- /dev/null +++ b/testsuite/pytests/test_spatial/test_axonal_delay.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# +# test_axonal_delay.py +# +# This file is part of NEST. +# +# Copyright (C) 2004 The NEST Initiative +# +# NEST is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# NEST is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with NEST. If not, see . + +""" +Test setting axonal and dendritic delays for models supporting this and those that don't, which must throw an exception. + +The test checks that weights and delays in a spatial network can be set to arbitrary values within the limits set by +resolution. The test creates a layer with a single row and uses linear functions for weights and delays. Expected +combined dendritic and axonal delays with resolution 0.04 are 1.0 0.96 0.96 0.92 0.92 0.88 0.84. One model supports +setting dendritic and axonal delays and one does not, which is expected to throw an exception. +""" + +import nest +import numpy as np +import pytest + + +def build_network(synapse_model): + """Build spatial network.""" + + nest.ResetKernel() + nest.resolution = 0.04 + nest.use_compressed_spikes = False + + p1 = nest.CreateParameter("constant", {"value": 0.5}) + p2 = nest.CreateParameter("constant", {"value": -0.01}) + p3 = nest.CreateParameter("distance", {}) + linear_parameter = p1 + p2 * p3 + + syn_spec = { + "synapse_model": synapse_model, + "weight": linear_parameter, + "dendritic_delay": linear_parameter, + "axonal_delay": linear_parameter, + } + pos = nest.spatial.grid( + shape=[10, 1], + extent=[10.0, 1.0], + center=[0.0, 0.0], + edge_wrap=True, + ) + conn_spec = { + "rule": "pairwise_bernoulli", + "use_on_source": False, + "mask": {"grid": {"shape": [10, 1]}, "anchor": [0, 0]}, + } + + src_layer = nest.Create("iaf_psc_alpha", positions=pos) + tgt_layer = nest.Create("iaf_psc_alpha", positions=pos) + + nest.Connect(src_layer, tgt_layer, conn_spec=conn_spec, syn_spec=syn_spec) + + return src_layer, tgt_layer + + +def test_layer_connections_dump_success(tmp_path, expected_conn_dump): + """Test that layer connections dump matches expectation.""" + + synapse_model = "stdp_pl_synapse_hom_ax_delay" + src_layer, tgt_layer = build_network(synapse_model) + + fname = tmp_path / "layer_conns.txt" + nest.DumpLayerConnections(src_layer, tgt_layer, synapse_model, fname) + + # We need to sort results to be invariant against implementation-dependent output order + actual_conn_dump = fname.read_text().splitlines() + assert actual_conn_dump.sort() == expected_conn_dump.sort() + + +def test_layer_connections_dump_failure(): + """Test that this synapse model is not compatible with the layer parameters.""" + + with pytest.raises(nest.kernel.NESTError): + build_network("static_synapse") + + +@pytest.fixture(scope="module") +def expected_conn_dump(): + expected_conn_dump = [ + "1 11 1 1 0 0", + "1 12 0.98 1 1 0", + "1 13 0.96 0.96 2 0", + "1 14 0.94 0.96 3 0", + "1 15 0.92 0.92 4 0", + "1 16 0.9 0.92 -5 0", + "1 17 0.92 0.92 -4 0", + "1 18 0.94 0.96 -3 0", + "1 19 0.96 0.96 -2 0", + "1 20 0.98 1 -1 0", + "2 11 0.98 1 -1 0", + "2 12 1 1 0 0", + "2 13 0.98 1 1 0", + "2 14 0.96 0.96 2 0", + "2 15 0.94 0.96 3 0", + "2 16 0.92 0.92 4 0", + "2 17 0.9 0.92 -5 0", + "2 18 0.92 0.92 -4 0", + "2 19 0.94 0.96 -3 0", + "2 20 0.96 0.96 -2 0", + "3 11 0.96 0.96 -2 0", + "3 12 0.98 1 -1 0", + "3 13 1 1 0 0", + "3 14 0.98 1 1 0", + "3 15 0.96 0.96 2 0", + "3 16 0.94 0.96 3 0", + "3 17 0.92 0.92 4 0", + "3 18 0.9 0.92 -5 0", + "3 19 0.92 0.92 -4 0", + "3 20 0.94 0.96 -3 0", + "4 11 0.94 0.96 -3 0", + "4 12 0.96 0.96 -2 0", + "4 13 0.98 1 -1 0", + "4 14 1 1 0 0", + "4 15 0.98 1 1 0", + "4 16 0.96 0.96 2 0", + "4 17 0.94 0.96 3 0", + "4 18 0.92 0.92 4 0", + "4 19 0.9 0.92 -5 0", + "4 20 0.92 0.92 -4 0", + "5 11 0.92 0.92 -4 0", + "5 12 0.94 0.96 -3 0", + "5 13 0.96 0.96 -2 0", + "5 14 0.98 1 -1 0", + "5 15 1 1 0 0", + "5 16 0.98 1 1 0", + "5 17 0.96 0.96 2 0", + "5 18 0.94 0.96 3 0", + "5 19 0.92 0.92 4 0", + "5 20 0.9 0.92 -5 0", + "6 11 0.9 0.92 -5 0", + "6 12 0.92 0.92 -4 0", + "6 13 0.94 0.96 -3 0", + "6 14 0.96 0.96 -2 0", + "6 15 0.98 1 -1 0", + "6 16 1 1 0 0", + "6 17 0.98 1 1 0", + "6 18 0.96 0.96 2 0", + "6 19 0.94 0.96 3 0", + "6 20 0.92 0.92 4 0", + "7 11 0.92 0.92 4 0", + "7 12 0.9 0.92 -5 0", + "7 13 0.92 0.92 -4 0", + "7 14 0.94 0.96 -3 0", + "7 15 0.96 0.96 -2 0", + "7 16 0.98 1 -1 0", + "7 17 1 1 0 0", + "7 18 0.98 1 1 0", + "7 19 0.96 0.96 2 0", + "7 20 0.94 0.96 3 0", + "8 11 0.94 0.96 3 0", + "8 12 0.92 0.92 4 0", + "8 13 0.9 0.92 -5 0", + "8 14 0.92 0.92 -4 0", + "8 15 0.94 0.96 -3 0", + "8 16 0.96 0.96 -2 0", + "8 17 0.98 1 -1 0", + "8 18 1 1 0 0", + "8 19 0.98 1 1 0", + "8 20 0.96 0.96 2 0", + "9 11 0.96 0.96 2 0", + "9 12 0.94 0.96 3 0", + "9 13 0.92 0.92 4 0", + "9 14 0.9 0.92 -5 0", + "9 15 0.92 0.92 -4 0", + "9 16 0.94 0.96 -3 0", + "9 17 0.96 0.96 -2 0", + "9 18 0.98 1 -1 0", + "9 19 1 1 0 0", + "9 20 0.98 1 1 0", + "10 11 0.98 1 1 0", + "10 12 0.96 0.96 2 0", + "10 13 0.94 0.96 3 0", + "10 14 0.92 0.92 4 0", + "10 15 0.9 0.92 -5 0", + "10 16 0.92 0.92 -4 0", + "10 17 0.94 0.96 -3 0", + "10 18 0.96 0.96 -2 0", + "10 19 0.98 1 -1 0", + "10 20 1 1 0 0", + ] + return expected_conn_dump diff --git a/testsuite/pytests/test_spatial/test_weight_delay.py b/testsuite/pytests/test_spatial/test_weight_delay.py index f0569d80b0..bb126fdaff 100644 --- a/testsuite/pytests/test_spatial/test_weight_delay.py +++ b/testsuite/pytests/test_spatial/test_weight_delay.py @@ -85,7 +85,7 @@ def build_network(layer_type): @pytest.mark.parametrize("layer_type", ["grid", "free"]) def test_source_layer_nodes_dump(tmp_path, expected_source_nodes_dump, layer_type): - """Test that source layer nodes dump mathces expectation.""" + """Test that source layer nodes dump matches expectation.""" src_layer, _ = build_network(layer_type) @@ -98,7 +98,7 @@ def test_source_layer_nodes_dump(tmp_path, expected_source_nodes_dump, layer_typ @pytest.mark.parametrize("layer_type", ["grid", "free"]) def test_target_layer_nodes_dump(tmp_path, expected_target_nodes_dump, layer_type): - """Test that target layer nodes dump mathces expectation.""" + """Test that target layer nodes dump matches expectation.""" _, tgt_layer = build_network(layer_type) @@ -111,7 +111,7 @@ def test_target_layer_nodes_dump(tmp_path, expected_target_nodes_dump, layer_typ @pytest.mark.parametrize("layer_type", ["grid", "free"]) def test_layer_connections_dump(tmp_path, expected_conn_dump, layer_type): - """Test that layer connections dump mathces expectation.""" + """Test that layer connections dump matches expectation.""" src_layer, tgt_layer = build_network(layer_type) diff --git a/testsuite/pytests/test_stdp_pl_synapse_hom.py b/testsuite/pytests/test_stdp_pl_synapse_hom.py index 4243ccc004..a635380882 100644 --- a/testsuite/pytests/test_stdp_pl_synapse_hom.py +++ b/testsuite/pytests/test_stdp_pl_synapse_hom.py @@ -36,6 +36,9 @@ except Exception: DEBUG_PLOTS = False +# Defined here so we can use it in init_params() and in parametrization +RESOLUTION = 0.1 # [ms] + @nest.ll_api.check_stack class TestSTDPPlSynapse: @@ -47,9 +50,8 @@ class TestSTDPPlSynapse: """ def init_params(self): - self.resolution = 0.1 # [ms] - self.simulation_duration = 1e3 # [ms] - self.synapse_model = "stdp_pl_synapse_hom" + self.simulation_duration = 1e2 # [ms] + self.synapse_model = "stdp_pl_synapse_hom_ax_delay" self.presynaptic_firing_rate = 100.0 # [ms^-1] self.postsynaptic_firing_rate = 100.0 # [ms^-1] self.tau_pre = 20.0 @@ -85,23 +87,27 @@ def do_nest_simulation_and_compare_to_reproduced_weight(self, fname_snip): weight_reproduced_independently, Kpre_log, Kpost_log, + allowed_to_deviate, ) = self.reproduce_weight_drift(pre_spikes, post_spikes, self.init_weight, fname_snip=fname_snip) # ``weight_by_nest`` contains only weight values at pre spike times, ``weight_reproduced_independently`` # contains the weight at pre *and* post times: check that weights are equal only for pre spike times assert len(weight_by_nest) > 0 - difference_matrix = t_weight_by_nest[t_weight_by_nest < self.simulation_duration].reshape( - 1, -1 - ) - t_weight_reproduced_independently.reshape(-1, 1) + difference_matrix = ( + t_weight_by_nest[t_weight_by_nest < self.simulation_duration].reshape(1, -1) + + self.axonal_delay + - t_weight_reproduced_independently.reshape(-1, 1) + ) pre_spike_reproduced_indices = np.abs(difference_matrix).argmin(axis=0) time_differences = np.diagonal(difference_matrix[pre_spike_reproduced_indices]) # make sure all spike times are equal np.testing.assert_allclose(time_differences, 0, atol=1e-07) + weights_to_consider = ~allowed_to_deviate[pre_spike_reproduced_indices] # make sure the weights after the pre_spikes times are equal np.testing.assert_allclose( - weight_by_nest[t_weight_by_nest < self.simulation_duration], - weight_reproduced_independently[pre_spike_reproduced_indices], + weight_by_nest[t_weight_by_nest < self.simulation_duration][weights_to_consider], + weight_reproduced_independently[pre_spike_reproduced_indices][weights_to_consider], ) if DEBUG_PLOTS: @@ -133,13 +139,7 @@ def do_the_nest_simulation(self): """ nest.set_verbosity("M_WARNING") nest.ResetKernel() - nest.SetKernelStatus( - { - "resolution": self.resolution, - "min_delay": min(self.min_delay, self.dendritic_delay), - "max_delay": max(self.max_delay, self.dendritic_delay), - } - ) + nest.SetKernelStatus({"resolution": RESOLUTION, "min_delay": self.min_delay, "max_delay": self.max_delay}) presynaptic_neuron, postsynaptic_neuron = nest.Create(self.nest_neuron_model, 2, params=self.neuron_parameters) @@ -171,6 +171,7 @@ def do_the_nest_simulation(self): {"spike_times": self.hardcoded_post_times + self.simulation_duration - self.hardcoded_trains_length}, ), ) + pre_spike_generator = spike_senders[0] post_spike_generator = spike_senders[1] @@ -234,19 +235,20 @@ def depress(w, Kminus): w_log = [] Kplus_log = [] Kminus_log = [] + allowed_to_deviate = [] # Make sure only spikes that were relevant for simulation are actually considered in the test # For pre-spikes that will be all spikes with: t_pre < sim_duration - pre_spikes = pre_spikes[pre_spikes + eps < self.simulation_duration] - # For post-spikes that will be all spikes with: t_post + d_dend <= latest_pre_spike - post_spikes = post_spikes[post_spikes + self.dendritic_delay <= pre_spikes[-1] + eps] + pre_spikes_delayed = pre_spikes[pre_spikes + eps < self.simulation_duration] + self.axonal_delay + # For post-spikes that will be all spikes with: t_post + d_dend <= latest_pre_spike + d_axon post_spikes_delayed = post_spikes + self.dendritic_delay + post_spikes_delayed = post_spikes_delayed[post_spikes_delayed <= pre_spikes_delayed[-1] + eps] - while idx_next_pre_spike < len(pre_spikes) or idx_next_post_spike < len(post_spikes_delayed): - if idx_next_pre_spike >= pre_spikes.size: + while idx_next_pre_spike < len(pre_spikes_delayed) or idx_next_post_spike < len(post_spikes_delayed): + if idx_next_pre_spike >= pre_spikes_delayed.size: t_next_pre_spike = -1 else: - t_next_pre_spike = pre_spikes[idx_next_pre_spike] + t_next_pre_spike = pre_spikes_delayed[idx_next_pre_spike] if idx_next_post_spike >= post_spikes_delayed.size: t_next_post_spike = -1 @@ -288,11 +290,36 @@ def depress(w, Kminus): if not handle_pre_spike or abs(t_next_post_spike - t_last_post_spike) > eps: if abs(t_next_post_spike - t_last_pre_spike) > eps: weight = facilitate(weight, Kplus) + # if time when next pre-synaptic spike is being communicated is before post-synaptic spike + # occurs, a correction will be required in NEST + if ( + t_next_pre_spike - RESOLUTION - self.axonal_delay + self.min_delay + ) // self.min_delay * self.min_delay < t_next_post_spike: + allowed_to_deviate.append(True) + else: + allowed_to_deviate.append(False) if handle_pre_spike: if not handle_post_spike or abs(t_next_pre_spike - t_last_pre_spike) > eps: if abs(t_next_pre_spike - t_last_post_spike) > eps: weight = depress(weight, Kminus) + # if the next post-synaptic spike occurs after the pre-synaptic is being communicated, but + # before the pre-synaptic spike arrives at the synapse, a correction will be required in NEST + if ( + abs(t_next_post_spike - t_next_pre_spike) < eps + and (t_next_pre_spike - RESOLUTION - self.axonal_delay + self.min_delay) + // self.min_delay + * self.min_delay + < t_next_post_spike - self.dendritic_delay + ): + pass + elif ( + t_next_pre_spike - RESOLUTION - self.axonal_delay + self.min_delay + ) // self.min_delay * self.min_delay < t_last_post_spike: + allowed_to_deviate.append(True) + else: + allowed_to_deviate.append(False) + t_last_pre_spike = t_next_pre_spike Kplus += 1.0 @@ -318,7 +345,7 @@ def depress(w, Kminus): title_snip="Reference", ) - return np.array(t_log), np.array(w_log), Kplus_log, Kminus_log + return np.array(t_log), np.array(w_log), Kplus_log, Kminus_log, np.array(allowed_to_deviate) def plot_weight_evolution( self, @@ -368,17 +395,23 @@ def plot_weight_evolution( fig.savefig("./tmp/nest_stdp_pl_synapse_hom_test" + fname_snip + ".png", dpi=300) plt.close(fig) - def test_stdp_synapse(self): + @pytest.mark.parametrize( + ["dend_delay", "ax_delay"], ((1.0, 0.0), (0.5, 0.5), (0.0, 1.0), (RESOLUTION, 0.0), (0.0, RESOLUTION)) + ) + @pytest.mark.parametrize("model", ("iaf_psc_alpha",)) + @pytest.mark.parametrize("min_delay", (1.0, 0.4, RESOLUTION)) + @pytest.mark.parametrize("max_delay", (1.0, 3.0)) + @pytest.mark.parametrize("t_ref", (RESOLUTION, 0.5, 1.0, 1.1, 2.5)) + def test_stdp_synapse(self, dend_delay, ax_delay, model, min_delay, max_delay, t_ref): self.init_params() - for self.dendritic_delay in (1.0, 0.5, self.resolution): - self.synapse_parameters["delay"] = self.dendritic_delay - for self.min_delay in (1.0, 0.4, self.resolution): - for self.max_delay in (3.0, 1.0): - self.min_delay = min(self.min_delay, self.max_delay) - self.max_delay = max(self.min_delay, self.max_delay) - for self.nest_neuron_model in ("iaf_psc_exp", "iaf_cond_exp"): - for self.neuron_parameters["t_ref"] in (self.resolution, 0.5, 1.0, 1.1, 2.5): - fname_snip = "_[nest_neuron_mdl=" + self.nest_neuron_model + "]" - fname_snip += "_[dend_delay=" + str(self.dendritic_delay) + "]" - fname_snip += "_[t_ref=" + str(self.neuron_parameters["t_ref"]) + "]" - self.do_nest_simulation_and_compare_to_reproduced_weight(fname_snip=fname_snip) + self.synapse_parameters["dendritic_delay"] = self.dendritic_delay = dend_delay + self.synapse_parameters["axonal_delay"] = self.axonal_delay = ax_delay + self.nest_neuron_model = model + self.min_delay = min(min_delay, max_delay, self.dendritic_delay + self.axonal_delay) + self.max_delay = max(min_delay, max_delay, self.dendritic_delay + self.axonal_delay) + self.neuron_parameters["t_ref"] = t_ref + + fname_snip = "_[nest_neuron_mdl=" + self.nest_neuron_model + "]" + fname_snip += "_[dend_delay=" + str(self.dendritic_delay) + "]" + fname_snip += "_[t_ref=" + str(self.neuron_parameters["t_ref"]) + "]" + self.do_nest_simulation_and_compare_to_reproduced_weight(fname_snip=fname_snip) diff --git a/testsuite/pytests/test_stdp_synapse.py b/testsuite/pytests/test_stdp_synapse.py index ccd0981c6d..1ff69c9e4c 100644 --- a/testsuite/pytests/test_stdp_synapse.py +++ b/testsuite/pytests/test_stdp_synapse.py @@ -51,7 +51,6 @@ class TestSTDPSynapse: """ def init_params(self): - self.resolution = RESOLUTION # [ms] self.simulation_duration = 1000 # [ms] self.synapse_model = "stdp_synapse" self.presynaptic_firing_rate = 100.0 # [ms^-1] @@ -71,9 +70,7 @@ def init_params(self): "Wmax": 15.0, "weight": self.init_weight, } - self.neuron_parameters = { - "tau_minus": self.tau_post, - } + self.neuron_parameters = {"tau_minus": self.tau_post} # While the random sequences, fairly long, would supposedly reveal small differences in the weight change # between NEST and ours, some low-probability events (say, coinciding spikes) can well not have occurred. @@ -154,7 +151,7 @@ def do_the_nest_simulation(self): nest.ResetKernel() nest.SetKernelStatus( { - "resolution": self.resolution, + "resolution": RESOLUTION, "min_delay": min(self.min_delay, self.dendritic_delay), "max_delay": max(self.max_delay, self.dendritic_delay), } @@ -399,7 +396,7 @@ def plot_weight_evolution( _ax.set_xlim(0.0, self.simulation_duration) fig.suptitle(title_snip) - fig.savefig("/tmp/nest_stdp_synapse_test" + fname_snip + ".png", dpi=300) + fig.savefig("./tmp/nest_stdp_synapse_test" + fname_snip + ".png", dpi=300) plt.close(fig) @pytest.mark.parametrize("dend_delay", [RESOLUTION, 1.0]) @@ -409,12 +406,11 @@ def plot_weight_evolution( @pytest.mark.parametrize("t_ref", (RESOLUTION, 0.5, 1.0, 1.1, 2.5)) def test_stdp_synapse(self, dend_delay, model, min_delay, max_delay, t_ref): self.init_params() - self.dendritic_delay = dend_delay + self.synapse_parameters["delay"] = self.dendritic_delay = dend_delay self.nest_neuron_model = model - self.min_delay = min(min_delay, max_delay) - self.max_delay = max(min_delay, max_delay) + self.min_delay = min(min_delay, max_delay, self.dendritic_delay) + self.max_delay = max(min_delay, max_delay, self.dendritic_delay) self.neuron_parameters["t_ref"] = t_ref - self.synapse_parameters["delay"] = self.dendritic_delay fname_snip = "_[nest_neuron_mdl=" + self.nest_neuron_model + "]" fname_snip += "_[dend_delay=" + str(self.dendritic_delay) + "]" diff --git a/testsuite/pytests/test_synapsecollection.py b/testsuite/pytests/test_synapsecollection.py index 67a590d4d8..55116c1b4a 100644 --- a/testsuite/pytests/test_synapsecollection.py +++ b/testsuite/pytests/test_synapsecollection.py @@ -117,7 +117,11 @@ def test_get(self): expected_syn_id = nest.GetDefaults("static_synapse", "synapse_modelid") target_ref = [1, 2, 1, 2] - dpw_ref = {"delay": [1.0, 1.0, 1.0, 1.0], "port": [0, 1, 2, 3], "weight": [1.0, 1.0, 1.0, 1.0]} + dpw_ref = { + "delay": [1.0, 1.0, 1.0, 1.0], + "port": [0, 1, 2, 3], + "weight": [1.0, 1.0, 1.0, 1.0], + } all_ref = { "delay": [1.0, 1.0, 1.0, 1.0], "port": [0, 1, 2, 3], diff --git a/testsuite/pytests/test_urbanczik_synapse.py b/testsuite/pytests/test_urbanczik_synapse.py index 0b057fdd0a..0dfef42904 100644 --- a/testsuite/pytests/test_urbanczik_synapse.py +++ b/testsuite/pytests/test_urbanczik_synapse.py @@ -229,7 +229,7 @@ def test_SynapseDepressionFacilitation(self): if len(spike_times_soma) > 0: t = np.around(t, 4) spike_times_soma = np.around(spike_times_soma + 0.2, 4) - idx = np.nonzero(np.in1d(t, spike_times_soma))[0] + idx = np.nonzero(np.isin(t, spike_times_soma))[0] rate[idx] -= 1.0 / resolution w_change_raw = -15.0 * C_m_prox * rate * h * alpha_response @@ -247,7 +247,7 @@ def test_SynapseDepressionFacilitation(self): comparison between Nest and python implementation """ # extract the weight computed in python at the times of the presynaptic spikes - idx = np.nonzero(np.in1d(np.around(t, 4), np.around(pre_syn_spike_times + resolution, 4)))[0] + idx = np.nonzero(np.isin(np.around(t, 4), np.around(pre_syn_spike_times + resolution, 4)))[0] syn_w_comp_at_spike_times = syn_weight_comp[idx] realtive_error = (weights[-1] - syn_w_comp_at_spike_times[-1]) / (weights[-1] - init_w)