From f4b4941fecd2c65ddd0785d6df9ffdba40470b73 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Fri, 8 Aug 2025 20:56:29 +0200 Subject: [PATCH 01/15] Fixed horrible kernel_manager singleton design and cleaned up all circular include chains --- .../guidelines/coding_guidelines_cpp.rst | 632 ++++++++---- .../spatially_structured_networks.rst | 1 - libnestutil/dict_util.h | 2 +- models/CMakeLists.txt | 8 +- models/ac_generator.cpp | 4 +- models/aeif_cond_alpha.cpp | 2 - models/aeif_cond_alpha_astro.cpp | 2 - models/aeif_cond_alpha_multisynapse.cpp | 2 - models/aeif_cond_beta_multisynapse.cpp | 2 - models/aeif_cond_exp.cpp | 2 - models/aeif_psc_alpha.cpp | 2 - models/aeif_psc_delta.cpp | 2 - models/aeif_psc_delta_clopath.cpp | 2 - models/aeif_psc_exp.cpp | 2 - models/amat2_psc_exp.cpp | 2 - models/astrocyte_lr_1994.cpp | 2 - models/bernoulli_synapse.cpp | 3 - models/binary_neuron.h | 1 - models/clopath_synapse.cpp | 3 - models/cm_compartmentcurrents.h | 2 + models/cm_default.cpp | 3 - models/cm_tree.cpp | 3 + models/cm_tree.h | 1 - models/cont_delay_synapse.cpp | 4 - models/cont_delay_synapse.h | 68 ++ models/cont_delay_synapse_impl.h | 109 --- models/correlation_detector.cpp | 4 - models/correlomatrix_detector.cpp | 2 - models/correlospinmatrix_detector.cpp | 2 - models/dc_generator.cpp | 3 - models/diffusion_connection.cpp | 3 - models/eprop_iaf.cpp | 3 - models/eprop_iaf.h | 1 - models/eprop_iaf_adapt.cpp | 3 - models/eprop_iaf_adapt.h | 1 - models/eprop_iaf_adapt_bsshslm_2020.cpp | 3 - models/eprop_iaf_adapt_bsshslm_2020.h | 1 - models/eprop_iaf_bsshslm_2020.cpp | 3 - models/eprop_iaf_bsshslm_2020.h | 1 - models/eprop_iaf_psc_delta.cpp | 3 - models/eprop_iaf_psc_delta.h | 1 - models/eprop_iaf_psc_delta_adapt.cpp | 3 - models/eprop_iaf_psc_delta_adapt.h | 1 - models/eprop_learning_signal_connection.cpp | 1 - ...earning_signal_connection_bsshslm_2020.cpp | 1 - models/eprop_readout.cpp | 2 - models/eprop_readout.h | 1 - models/eprop_readout_bsshslm_2020.cpp | 2 - models/eprop_readout_bsshslm_2020.h | 1 - models/eprop_synapse.cpp | 1 - models/eprop_synapse_bsshslm_2020.cpp | 1 - models/erfc_neuron.cpp | 3 - models/gamma_sup_generator.cpp | 7 +- models/gap_junction.cpp | 3 - models/gauss_rate.cpp | 2 - models/gauss_rate.h | 2 - models/gif_cond_exp.cpp | 2 - models/gif_cond_exp_multisynapse.cpp | 2 - models/gif_pop_psc_exp.cpp | 6 - models/gif_psc_exp.cpp | 7 +- models/gif_psc_exp_multisynapse.cpp | 2 - models/ginzburg_neuron.cpp | 3 - models/glif_cond.cpp | 6 +- models/glif_psc.cpp | 10 - models/glif_psc.h | 6 + models/glif_psc_double_alpha.cpp | 6 +- models/hh_cond_beta_gap_traub.cpp | 2 - models/hh_cond_exp_traub.cpp | 2 - models/hh_psc_alpha.cpp | 3 - models/hh_psc_alpha_clopath.cpp | 3 - models/hh_psc_alpha_gap.cpp | 2 - models/ht_neuron.cpp | 2 - models/ht_synapse.cpp | 3 - models/iaf_bw_2001.cpp | 6 +- models/iaf_bw_2001_exact.cpp | 6 +- models/iaf_chs_2007.cpp | 2 - models/iaf_chxk_2008.cpp | 2 - models/iaf_cond_alpha.cpp | 2 - models/iaf_cond_alpha_mc.cpp | 2 - models/iaf_cond_beta.cpp | 2 - models/iaf_cond_exp.cpp | 2 - models/iaf_cond_exp_sfa_rr.cpp | 2 - models/iaf_psc_alpha.cpp | 3 - models/iaf_psc_alpha_multisynapse.cpp | 2 - models/iaf_psc_alpha_ps.cpp | 2 - models/iaf_psc_delta.cpp | 2 - models/iaf_psc_delta_ps.cpp | 2 - models/iaf_psc_exp.cpp | 3 - models/iaf_psc_exp_htum.cpp | 2 - models/iaf_psc_exp_multisynapse.cpp | 2 - models/iaf_psc_exp_ps.cpp | 2 - models/iaf_psc_exp_ps_lossless.cpp | 2 - models/iaf_tum_2000.cpp | 3 - models/ignore_and_fire.cpp | 4 - models/ignore_and_fire.h | 24 +- models/inhomogeneous_poisson_generator.cpp | 3 - models/izhikevich.cpp | 3 - models/jonke_synapse.cpp | 3 - models/lin_rate.cpp | 4 +- models/lin_rate.h | 3 - models/mat2_psc_exp.cpp | 2 - models/mcculloch_pitts_neuron.cpp | 3 - models/mip_generator.cpp | 3 +- models/multimeter.cpp | 6 +- models/music_cont_in_proxy.cpp | 1 - models/music_cont_out_proxy.cpp | 2 - models/music_event_in_proxy.cpp | 9 +- models/music_event_out_proxy.cpp | 4 +- models/music_message_in_proxy.cpp | 1 - models/music_rate_in_proxy.cpp | 2 - models/music_rate_out_proxy.cpp | 1 - models/noise_generator.cpp | 4 +- models/noise_generator.h | 2 - models/parrot_neuron.cpp | 9 - models/parrot_neuron_ps.cpp | 2 - models/poisson_generator.cpp | 3 +- models/poisson_generator_ps.cpp | 3 +- models/pp_cond_exp_mc_urbanczik.cpp | 3 - models/pp_cond_exp_mc_urbanczik.h | 1 - models/pp_psc_delta.cpp | 2 - models/ppd_sup_generator.cpp | 3 +- models/pulsepacket_generator.cpp | 4 +- models/quantal_stp_synapse.cpp | 4 - models/quantal_stp_synapse.h | 64 ++ models/quantal_stp_synapse_impl.h | 105 -- models/rate_connection_delayed.cpp | 3 - models/rate_connection_instantaneous.cpp | 3 - models/rate_neuron_ipn.h | 435 ++++++++- models/rate_neuron_ipn_impl.h | 479 --------- models/rate_neuron_opn.h | 411 +++++++- models/rate_neuron_opn_impl.h | 452 --------- models/rate_transformer_node.h | 262 +++++ models/rate_transformer_node_impl.h | 319 ------ models/sic_connection.cpp | 3 - models/siegert_neuron.cpp | 4 - models/sigmoid_rate.cpp | 5 +- models/sigmoid_rate.h | 2 - models/sigmoid_rate_gg_1998.cpp | 5 +- models/sigmoid_rate_gg_1998.h | 2 - models/sinusoidal_gamma_generator.cpp | 4 +- models/sinusoidal_gamma_generator.h | 1 - models/sinusoidal_poisson_generator.cpp | 4 +- models/spike_dilutor.cpp | 3 - models/spike_generator.cpp | 3 +- models/spike_recorder.cpp | 5 +- models/spike_train_injector.cpp | 4 +- models/spin_detector.cpp | 11 +- models/static_synapse.cpp | 3 - models/static_synapse.h | 2 + models/static_synapse_hom_w.cpp | 3 - models/stdp_dopamine_synapse.cpp | 3 - models/stdp_facetshw_synapse_hom.cpp | 4 - models/stdp_facetshw_synapse_hom.h | 296 ++++++ models/stdp_facetshw_synapse_hom_impl.h | 339 ------- models/stdp_nn_pre_centered_synapse.cpp | 3 - models/stdp_nn_restr_synapse.cpp | 3 - models/stdp_nn_symm_synapse.cpp | 3 - models/stdp_pl_synapse_hom.cpp | 2 - models/stdp_synapse.cpp | 3 - models/stdp_synapse_hom.cpp | 2 - models/stdp_triplet_synapse.cpp | 3 - models/step_current_generator.cpp | 3 - models/step_rate_generator.cpp | 3 - models/tanh_rate.cpp | 5 +- models/tanh_rate.h | 3 - models/threshold_lin_rate.cpp | 5 +- models/threshold_lin_rate.h | 3 - models/tsodyks2_synapse.cpp | 3 - models/tsodyks_synapse.cpp | 3 - models/tsodyks_synapse_hom.cpp | 4 - models/urbanczik_synapse.cpp | 3 - models/vogels_sprekeler_synapse.cpp | 3 - models/volume_transmitter.cpp | 4 - models/weight_recorder.cpp | 5 +- models/weight_recorder.h | 6 +- nestkernel/CMakeLists.txt | 46 +- nestkernel/archiving_node.cpp | 1 + nestkernel/buffer_resize_log.cpp | 2 + nestkernel/clopath_archiving_node.cpp | 1 + nestkernel/common_properties_hom_w.h | 2 + nestkernel/common_synapse_properties.cpp | 3 +- nestkernel/common_synapse_properties.h | 8 +- nestkernel/conn_builder.cpp | 7 +- nestkernel/conn_builder.h | 17 +- nestkernel/conn_builder_impl.h | 51 - nestkernel/connection.h | 1 - nestkernel/connection_creator.h | 867 +++++++++++++++++ nestkernel/connection_creator_impl.h | 907 ------------------ nestkernel/connection_label.h | 2 +- nestkernel/connection_manager.cpp | 170 ++-- nestkernel/connection_manager.h | 44 +- nestkernel/connection_manager_impl.h | 85 -- nestkernel/connector_base.cpp | 50 + nestkernel/connector_base.h | 44 +- nestkernel/connector_base_impl.h | 67 -- nestkernel/connector_model.cpp | 7 + nestkernel/connector_model.h | 8 +- nestkernel/connector_model_impl.h | 43 +- nestkernel/delay_checker.cpp | 7 + nestkernel/eprop_archiving_node.h | 155 +++ nestkernel/eprop_archiving_node_impl.h | 194 ---- nestkernel/eprop_archiving_node_recurrent.h | 266 +++++ .../eprop_archiving_node_recurrent_impl.h | 303 ------ nestkernel/event.cpp | 2 +- nestkernel/event_delivery_manager.cpp | 32 +- nestkernel/event_delivery_manager.h | 147 ++- nestkernel/event_delivery_manager_impl.h | 181 ---- nestkernel/free_layer.h | 2 +- nestkernel/genericmodel.h | 22 +- nestkernel/genericmodel_impl.h | 52 - nestkernel/io_manager.cpp | 3 +- nestkernel/io_manager.h | 49 +- nestkernel/io_manager_impl.h | 61 -- nestkernel/kernel_manager.cpp | 118 +-- nestkernel/kernel_manager.h | 109 +-- nestkernel/layer.cpp | 2 - nestkernel/layer.h | 173 +--- nestkernel/layer_impl.h | 180 +++- nestkernel/mask.h | 482 ++++++++++ nestkernel/mask_impl.h | 515 ---------- nestkernel/model.cpp | 1 + nestkernel/model_manager.cpp | 5 +- nestkernel/model_manager.h | 97 +- nestkernel/model_manager_impl.h | 126 --- nestkernel/modelrange_manager.cpp | 1 + nestkernel/mpi_manager.cpp | 12 +- nestkernel/mpi_manager.h | 50 +- nestkernel/mpi_manager_impl.h | 94 -- nestkernel/music_event_handler.cpp | 2 + nestkernel/music_manager.cpp | 3 + nestkernel/music_rate_in_handler.cpp | 4 +- nestkernel/nest.cpp | 9 +- nestkernel/nest.h | 22 +- nestkernel/nest_extension_interface.h | 7 - nestkernel/nestmodule.cpp | 13 +- nestkernel/node.cpp | 2 + nestkernel/node.h | 2 - nestkernel/node_collection.cpp | 6 +- nestkernel/node_manager.cpp | 8 +- nestkernel/ntree.h | 495 ++++++++++ nestkernel/ntree_impl.h | 532 ---------- nestkernel/parameter.cpp | 5 +- nestkernel/per_thread_bool_indicator.cpp | 19 +- nestkernel/proxynode.cpp | 1 + nestkernel/random_manager.cpp | 5 +- nestkernel/recording_backend_ascii.cpp | 8 +- nestkernel/recording_backend_memory.cpp | 5 +- nestkernel/recording_backend_mpi.cpp | 3 + nestkernel/recording_backend_sionlib.cpp | 4 +- nestkernel/recording_device.cpp | 5 +- nestkernel/ring_buffer.cpp | 1 + nestkernel/ring_buffer.h | 31 + nestkernel/ring_buffer_impl.h | 58 -- nestkernel/secondary_event.h | 25 + nestkernel/secondary_event_impl.h | 51 - nestkernel/simulation_manager.cpp | 63 +- nestkernel/simulation_manager.h | 24 + nestkernel/slice_ring_buffer.cpp | 3 + nestkernel/slice_ring_buffer.h | 2 +- nestkernel/sonata_connector.cpp | 1 - nestkernel/source_table.cpp | 15 +- nestkernel/sp_manager.cpp | 6 +- nestkernel/sp_manager.h | 12 + nestkernel/sp_manager_impl.h | 52 - nestkernel/sparse_node_array.cpp | 1 - nestkernel/spatial.cpp | 1 - nestkernel/stimulation_backend_mpi.cpp | 4 + nestkernel/stimulation_device.cpp | 1 + nestkernel/stopwatch.h | 91 +- nestkernel/stopwatch_impl.h | 112 --- nestkernel/synaptic_element.cpp | 2 + nestkernel/target_identifier.h | 2 + nestkernel/target_table.cpp | 3 + nestkernel/target_table_devices.cpp | 71 +- nestkernel/target_table_devices.h | 66 +- nestkernel/target_table_devices_impl.h | 138 --- nestkernel/universal_data_logger.h | 442 ++++++++- nestkernel/universal_data_logger_impl.h | 436 --------- nestkernel/urbanczik_archiving_node.h | 96 ++ nestkernel/urbanczik_archiving_node_impl.h | 131 --- nestkernel/vp_manager.cpp | 7 +- nestkernel/vp_manager.h | 133 ++- nestkernel/vp_manager_impl.h | 133 --- 283 files changed, 6368 insertions(+), 7358 deletions(-) delete mode 100644 models/cont_delay_synapse_impl.h delete mode 100644 models/rate_neuron_ipn_impl.h delete mode 100644 models/rate_neuron_opn_impl.h delete mode 100644 models/rate_transformer_node_impl.h delete mode 100644 models/stdp_facetshw_synapse_hom_impl.h delete mode 100644 nestkernel/conn_builder_impl.h delete mode 100644 nestkernel/connection_creator_impl.h delete mode 100644 nestkernel/connection_manager_impl.h create mode 100644 nestkernel/connector_base.cpp delete mode 100644 nestkernel/eprop_archiving_node_impl.h delete mode 100644 nestkernel/eprop_archiving_node_recurrent_impl.h delete mode 100644 nestkernel/event_delivery_manager_impl.h delete mode 100644 nestkernel/genericmodel_impl.h delete mode 100644 nestkernel/io_manager_impl.h delete mode 100644 nestkernel/mask_impl.h delete mode 100644 nestkernel/mpi_manager_impl.h delete mode 100644 nestkernel/ntree_impl.h delete mode 100644 nestkernel/ring_buffer_impl.h delete mode 100644 nestkernel/secondary_event_impl.h delete mode 100644 nestkernel/sp_manager_impl.h delete mode 100644 nestkernel/stopwatch_impl.h delete mode 100644 nestkernel/target_table_devices_impl.h delete mode 100644 nestkernel/universal_data_logger_impl.h delete mode 100644 nestkernel/urbanczik_archiving_node_impl.h delete mode 100644 nestkernel/vp_manager_impl.h diff --git a/doc/htmldoc/developer_space/guidelines/coding_guidelines_cpp.rst b/doc/htmldoc/developer_space/guidelines/coding_guidelines_cpp.rst index f6dceba360..e906a612b7 100644 --- a/doc/htmldoc/developer_space/guidelines/coding_guidelines_cpp.rst +++ b/doc/htmldoc/developer_space/guidelines/coding_guidelines_cpp.rst @@ -371,171 +371,175 @@ For example, the ``stopwatch.h`` file could look like: #ifndef STOPWATCH_H #define STOPWATCH_H - // C includes: - #include - // C++ includes: - #include + #include #include + #include + + // Includes from nestkernel: + #include "arraydatum.h" + #include "dictdatum.h" + #include "dictutils.h" + #include "exceptions.h" + #include "kernel_manager.h" + #include "vp_manager.h" namespace nest { - /*********************************************************************** - * Stopwatch * - * Accumulates time between start and stop, and provides * - * the elapsed time with different time units. * - * * - * Partly inspired by com.google.common.base.Stopwatch.java * - * Not thread-safe: - Do not share stopwatches among threads. * - * - Let each thread have its own stopwatch. * - * * - * Usage example: * - * Stopwatch x; * - * x.start(); * - * // ... do computations for 15.34 sec * - * x.stop(); // only pauses stopwatch * - * x.print("Time needed "); // > Time needed 15.34 sec. * - * x.start(); // resumes stopwatch * - * // ... next computations for 11.22 sec * - * x.stop(); * - * x.print("Time needed "); // > Time needed 26,56 sec. * - * x.reset(); // reset to default values * - * x.start(); // starts the stopwatch from 0 * - * // ... computation 5.7 sec * - * x.print("Time "); // > Time 5.7 sec. * - * // ^ intermediate timing without stopping the stopwatch * - * // ... more computations 1.7643 min * - * x.stop(); * - * x.print("Time needed ", Stopwatch::MINUTES, std::cerr); * - * // > Time needed 1,8593 min. (on cerr) * - * // other units and output streams possible * - ***********************************************************************/ - class Stopwatch + #ifdef TIMER_DETAILED + constexpr bool use_detailed_timers = true; + #else + constexpr bool use_detailed_timers = false; + #endif + #ifdef THREADED_TIMERS + constexpr bool use_threaded_timers = true; + #else + constexpr bool use_threaded_timers = false; + #endif + + enum class StopwatchGranularity { - public: - typedef size_t timestamp_t; - typedef size_t timeunit_t; + Normal, // + class Stopwatch; + + /******************************************************************************** + * Stopwatch * + * Accumulates time between start and stop, and provides the elapsed time * + * with different time units. Either runs multi-threaded or only on master. * + * * + * Usage example: * + * Stopwatch< StopwatchGranularity::Normal, StopwatchParallelism::MasterOnly > x; * + * x.start(); * + * // ... do computations for 15.34 sec * + * x.stop(); // only pauses stopwatch * + * x.print("Time needed "); // > Time needed 15.34 sec. * + * x.start(); // resumes stopwatch * + * // ... next computations for 11.22 sec * + * x.stop(); * + * x.print("Time needed "); // > Time needed 26,56 sec. * + * x.reset(); // reset to default values * + * x.start(); // starts the stopwatch from 0 * + * // ... computation 5.7 sec * + * x.print("Time "); // > Time 5.7 sec. * + * // ^ intermediate timing without stopping the stopwatch * + * // ... more computations 1.7643 min * + * x.stop(); * + * x.print("Time needed ", timeunit_t::MINUTES, std::cerr); * + * // > Time needed 1,8593 min. (on cerr) * + * // other units and output streams possible * + ********************************************************************************/ + namespace timers + { + enum class timeunit_t : size_t + { + NANOSEC = 1, + MICROSEC = NANOSEC * 1000, + MILLISEC = MICROSEC * 1000, + SECONDS = MILLISEC * 1000, + MINUTES = SECONDS * 60, + HOURS = MINUTES * 60, + DAYS = HOURS * 24 + }; - /** - * Creates a stopwatch that is not running. - */ - Stopwatch() + /** This class represents a single timer which measures the execution time of a single thread for a given clock type. + * Typical clocks are monotonic wall-time clocks or clocks just measuring cpu time. + */ + template < clockid_t clock_type > + class StopwatchTimer + { + template < StopwatchGranularity, StopwatchParallelism, typename > + friend class nest::Stopwatch; + + public: + typedef size_t timestamp_t; + + //! Creates a stopwatch that is not running. + StopwatchTimer() { reset(); } - /** - * Starts or resumes the stopwatch, if it is not running already. - */ + //! Starts or resumes the stopwatch, if it is not running already. void start(); - /** - * Stops the stopwatch, if it is not stopped already. - */ + //! Stops the stopwatch, if it is not stopped already. void stop(); /** - * Returns, whether the stopwatch is running. - */ - bool isRunning() const; - - /** - * Returns the time elapsed between the start and stop of the - * stopwatch. If it is running, it returns the time from start - * until now. If the stopwatch is run previously, the previous - * runtime is added. If you want only the last measurment, you - * have to reset the timer, before stating the measurment. - * Does not change the running state. - */ - double elapsed( timeunit_t timeunit = SECONDS ) const; - - /** - * Returns the time elapsed between the start and stop of the - * stopwatch. If it is running, it returns the time from start - * until now. If the stopwatch is run previously, the previous - * runtime is added. If you want only the last measurment, you - * have to reset the timer, before stating the measurment. + * Returns the time elapsed between the start and stop of the stopwatch in the given unit. If it is running, it + * returns the time from start until now. If the stopwatch is run previously, the previous runtime is added. If you + * want only the last measurement, you have to reset the timer, before stating the measurement. * Does not change the running state. - * In contrast to Stopwatch::elapsed(), only the timestamp is returned, - * that is the number if microseconds as an integer. */ - timestamp_t elapsed_timestamp() const; + double elapsed( timeunit_t timeunit = timeunit_t::SECONDS ) const; - /** - * Resets the stopwatch. - */ + //! Resets the stopwatch. void reset(); - /** - * This method prints out the currently elapsed time. - */ - void print( const char* msg = "", timeunit_t timeunit = SECONDS, std::ostream& os = std::cout ) const; - - /** - * Convenient method for writing time in seconds - * to some ostream. - */ - friend std::ostream& operator<<( std::ostream& os, const Stopwatch& stopwatch ); + //! This method prints out the currently elapsed time. + void + print( const std::string& msg = "", timeunit_t timeunit = timeunit_t::SECONDS, std::ostream& os = std::cout ) const; private: + //! Returns, whether the stopwatch is running. + bool is_running_() const; + #ifndef DISABLE_TIMING timestamp_t _beg, _end; size_t _prev_elapsed; bool _running; #endif - /** - * Returns current time in microseconds since EPOCH. - */ - static timestamp_t get_timestamp(); + //! Returns current time in microseconds since EPOCH. + static size_t get_current_time(); }; - inline bool - Stopwatch::correct_timeunit( timeunit_t t ) - { - return t == MICROSEC || t == MILLISEC || t == SECONDS || t == MINUTES || t == HOURS || t == DAYS; - } - + template < clockid_t clock_type > inline void - nest::Stopwatch::start() + StopwatchTimer< clock_type >::start() { #ifndef DISABLE_TIMING - if ( not isRunning() ) + if ( not is_running_() ) { - _prev_elapsed += _end - _beg; // store prev. time, if we resume - _end = _beg = get_timestamp(); // invariant: _end >= _beg - _running = true; // we start running + _prev_elapsed += _end - _beg; // store prev. time, if we resume + _end = _beg = get_current_time(); // invariant: _end >= _beg + _running = true; // we start running } #endif } + template < clockid_t clock_type > inline void - nest::Stopwatch::stop() + StopwatchTimer< clock_type >::stop() { #ifndef DISABLE_TIMING - if ( isRunning() ) + if ( is_running_() ) { - _end = get_timestamp(); // invariant: _end >= _beg - _running = false; // we stopped running + _end = get_current_time(); // invariant: _end >= _beg + _running = false; // we stopped running } #endif } + template < clockid_t clock_type > inline bool - nest::Stopwatch::isRunning() const + StopwatchTimer< clock_type >::is_running_() const { #ifndef DISABLE_TIMING return _running; @@ -544,38 +548,31 @@ For example, the ``stopwatch.h`` file could look like: #endif } + template < clockid_t clock_type > inline double - nest::Stopwatch::elapsed( timeunit_t timeunit ) const - { - #ifndef DISABLE_TIMING - assert( correct_timeunit( timeunit ) ); - return 1.0 * elapsed_timestamp() / timeunit; - #else - return 0.0; - #endif - } - - inline nest::Stopwatch::timestamp_t - nest::Stopwatch::elapsed_us() const + StopwatchTimer< clock_type >::elapsed( timeunit_t timeunit ) const { #ifndef DISABLE_TIMING - if ( isRunning() ) + size_t time_elapsed; + if ( is_running_() ) { // get intermediate elapsed time; do not change _end, to be const - return get_timestamp() - _beg + _prev_elapsed; + time_elapsed = get_current_time() - _beg + _prev_elapsed; } else { // stopped before, get time of current measurement + last measurements - return _end - _beg + _prev_elapsed; + time_elapsed = _end - _beg + _prev_elapsed; } + return static_cast< double >( time_elapsed ) / static_cast< double >( timeunit ); #else - return ( timestamp_t ) 0; + return 0.; #endif } + template < clockid_t clock_type > inline void - nest::Stopwatch::reset() + StopwatchTimer< clock_type >::reset() { #ifndef DISABLE_TIMING _beg = 0; // invariant: _end >= _beg @@ -585,33 +582,37 @@ For example, the ``stopwatch.h`` file could look like: #endif } + template < clockid_t clock_type > inline void - nest::Stopwatch::print( const char* msg, timeunit_t timeunit, std::ostream& os ) const + StopwatchTimer< clock_type >::print( const std::string& msg, timeunit_t timeunit, std::ostream& os ) const { #ifndef DISABLE_TIMING - assert( correct_timeunit( timeunit ) ); double e = elapsed( timeunit ); os << msg << e; switch ( timeunit ) { - case MICROSEC: + case timeunit_t::NANOSEC: + os << " nanosec."; + case timeunit_t::MICROSEC: os << " microsec."; break; - case MILLISEC: + case timeunit_t::MILLISEC: os << " millisec."; break; - case SECONDS: + case timeunit_t::SECONDS: os << " sec."; break; - case MINUTES: + case timeunit_t::MINUTES: os << " min."; break; - case HOURS: + case timeunit_t::HOURS: os << " h."; break; - case DAYS: + case timeunit_t::DAYS: os << " days."; break; + default: + throw BadParameter( "Invalid timeunit provided to stopwatch." ); } #ifdef DEBUG os << " (running: " << ( _running ? "true" : "false" ) << ", begin: " << _beg << ", end: " << _end @@ -621,55 +622,336 @@ For example, the ``stopwatch.h`` file could look like: #endif } - inline nest::Stopwatch::timestamp_t - nest::Stopwatch::get_current_time() + template < clockid_t clock_type > + inline size_t + StopwatchTimer< clock_type >::get_current_time() { - // works with: - // * hambach (Linux 2.6.32 x86_64) - // * JuQueen (BG/Q) - // * MacOS 10.9 - struct timeval now; - gettimeofday( &now, ( struct timezone* ) 0 ); - return ( nest::Stopwatch::timestamp_t ) now.tv_usec - + ( nest::Stopwatch::timestamp_t ) now.tv_sec * nest::Stopwatch::SECONDS; + timespec now; + clock_gettime( clock_type, &now ); + return now.tv_nsec + now.tv_sec * static_cast< long >( timeunit_t::SECONDS ); } - } /* namespace timer */ - #endif /* STOPWATCH_H */ + template < clockid_t clock_type > + inline std::ostream& + operator<<( std::ostream& os, const StopwatchTimer< clock_type >& stopwatch ) + { + stopwatch.print( "", timeunit_t::SECONDS, os ); + return os; + } -And the corresponding ``stopwatch_impl.h``: + } // namespace timers -.. code:: cpp - /* - * stopwatch_impl.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. + /** This is the base template for all Stopwatch specializations. * - * 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. + * This template will be specialized in case detailed timers are deactivated or the timer is supposed to be run by + * multiple threads. If the timer should be deactivated, because detailed timers are disabled, the template + * specialization will be empty and optimized away by the compiler. + * This base template only measures a single timer, owned by the master thread, which applies for both detailed and + * regular timers. Detailed, master-only timers that are deactivated when detailed timers are turned off are handled + * by one of the template specializations below. * - * You should have received a copy of the GNU General Public License - * along with NEST. If not, see . + * The template has three template arguments of which two act as actual parameters that need to be specified for each + * stopwatch instance. The first one "detailed_timer" controls the granularity of the stopwatch, i.e., if the timer is + * considered a normal or detailed timer. The second one "threaded_timer" defines if the timer is supposed to be + * measured by each thread individually. In case a timer is specified as threaded, but threaded timers are turned off + * globally, the stopwatch will run in master-only mode instead. The third template argument is used to enable or + * disable certain template specializations based on compiler flags (i.e., detailed timers and threaded timers). * + * In all cases, both the (monotonic) wall-time and cpu time are measured. */ + template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer, typename = void > + class Stopwatch + { + public: + void + start() + { + #pragma omp master + { + walltime_timer_.start(); + cputime_timer_.start(); + } + } - #include "stopwatch.h" + void + stop() + { + #pragma omp master + { + walltime_timer_.stop(); + cputime_timer_.stop(); + } + } - namespace nest + double + elapsed( timers::timeunit_t timeunit = timers::timeunit_t::SECONDS ) const + { + double elapsed = 0.; + #pragma omp master + { + elapsed = walltime_timer_.elapsed( timeunit ); + }; + return elapsed; + } + + void + reset() + { + #pragma omp master + { + walltime_timer_.reset(); + cputime_timer_.reset(); + } + } + + void + print( const std::string& msg = "", + timers::timeunit_t timeunit = timers::timeunit_t::SECONDS, + std::ostream& os = std::cout ) const + { + #pragma omp master + walltime_timer_.print( msg, timeunit, os ); + } + + void + get_status( DictionaryDatum& d, const Name& walltime_name, const Name& cputime_name ) const + { + def< double >( d, walltime_name, walltime_timer_.elapsed() ); + def< double >( d, cputime_name, cputime_timer_.elapsed() ); + } + + private: + bool + is_running_() const + { + bool is_running_ = false; + #pragma omp master + { + is_running_ = walltime_timer_.is_running_(); + }; + return is_running_; + } + + // We use a monotonic timer to make sure the stopwatch is not influenced by time jumps (e.g. summer/winter time). + timers::StopwatchTimer< CLOCK_MONOTONIC > walltime_timer_; + timers::StopwatchTimer< CLOCK_THREAD_CPUTIME_ID > cputime_timer_; + }; + + //! Stopwatch template specialization for detailed, master-only timer instances if detailed timers are deactivated. + template <> + class Stopwatch< StopwatchGranularity::Detailed, + StopwatchParallelism::MasterOnly, + std::enable_if< not use_detailed_timers > > { - std::ostream& operator<<( std::ostream& os, const Stopwatch& stopwatch ) + public: + void + start() + { + } + void + stop() + { + } + double + elapsed( timers::timeunit_t = timers::timeunit_t::SECONDS ) const + { + return 0; + } + void + reset() + { + } + void + print( const std::string& = "", timers::timeunit_t = timers::timeunit_t::SECONDS, std::ostream& = std::cout ) const + { + } + void + get_status( DictionaryDatum&, const Name&, const Name& ) const + { + } + + private: + bool + is_running_() const + { + return false; + } + }; + + //! Stopwatch template specialization for detailed, threaded timer instances if detailed timers are deactivated. + template < StopwatchGranularity detailed_timer > + class Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Detailed and not use_detailed_timers ) > > { - stopwatch.print( "", Stopwatch::SECONDS, os ); - return os; + public: + void + start() + { + } + void + stop() + { + } + double + elapsed( timers::timeunit_t = timers::timeunit_t::SECONDS ) const + { + return 0; + } + void + reset() + { + } + void + print( const std::string& = "", timers::timeunit_t = timers::timeunit_t::SECONDS, std::ostream& = std::cout ) const + { + } + void + get_status( DictionaryDatum&, const Name&, const Name& ) const + { + } + + private: + bool + is_running_() const + { + return false; + } + }; + + /** Stopwatch template specialization for threaded timer instances if the timer is a detailed one and detailed timers + * are activated or the timer is not a detailed one in the first place. + */ + template < StopwatchGranularity detailed_timer > + class Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > > + { + public: + void start(); + + void stop(); + + double elapsed( timers::timeunit_t timeunit = timers::timeunit_t::SECONDS ) const; + + void reset(); + + void print( const std::string& msg = "", + timers::timeunit_t timeunit = timers::timeunit_t::SECONDS, + std::ostream& os = std::cout ) const; + + void + get_status( DictionaryDatum& d, const Name& walltime_name, const Name& cputime_name ) const + { + std::vector< double > wall_times( walltime_timers_.size() ); + std::transform( walltime_timers_.begin(), + walltime_timers_.end(), + wall_times.begin(), + []( const timers::StopwatchTimer< CLOCK_MONOTONIC >& timer ) { return timer.elapsed(); } ); + def< ArrayDatum >( d, walltime_name, ArrayDatum( wall_times ) ); + + std::vector< double > cpu_times( cputime_timers_.size() ); + std::transform( cputime_timers_.begin(), + cputime_timers_.end(), + cpu_times.begin(), + []( const timers::StopwatchTimer< CLOCK_THREAD_CPUTIME_ID >& timer ) { return timer.elapsed(); } ); + def< ArrayDatum >( d, cputime_name, ArrayDatum( cpu_times ) ); + } + + private: + bool is_running_() const; + + // We use a monotonic timer to make sure the stopwatch is not influenced by time jumps (e.g. summer/winter time). + std::vector< timers::StopwatchTimer< CLOCK_MONOTONIC > > walltime_timers_; + std::vector< timers::StopwatchTimer< CLOCK_THREAD_CPUTIME_ID > > cputime_timers_; + }; + + template < StopwatchGranularity detailed_timer > + void + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::start() + { + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].start(); + cputime_timers_[ kernel().vp_manager.get_thread_id() ].start(); } + + template < StopwatchGranularity detailed_timer > + void + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::stop() + { + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); + cputime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); + } + + template < StopwatchGranularity detailed_timer > + bool + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::is_running_() const + { + kernel().vp_manager.assert_thread_parallel(); + + return walltime_timers_[ kernel().vp_manager.get_thread_id() ].is_running_(); + } + + template < StopwatchGranularity detailed_timer > + double + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::elapsed( timers::timeunit_t + timeunit ) const + { + kernel().vp_manager.assert_thread_parallel(); + + return walltime_timers_[ kernel().vp_manager.get_thread_id() ].elapsed( timeunit ); } + + template < StopwatchGranularity detailed_timer > + void + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::print( const std::string& msg, + timers::timeunit_t timeunit, + std::ostream& os ) const + { + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].print( msg, timeunit, os ); + } + + template < StopwatchGranularity detailed_timer > + void + Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::reset() + { + kernel().vp_manager.assert_single_threaded(); + + const size_t num_threads = kernel().vp_manager.get_num_threads(); + walltime_timers_.resize( num_threads ); + cputime_timers_.resize( num_threads ); + for ( size_t i = 0; i < num_threads; ++i ) + { + walltime_timers_[ i ].reset(); + cputime_timers_[ i ].reset(); + } + } + + } /* namespace nest */ + #endif /* STOPWATCH_H */ diff --git a/doc/htmldoc/networks/spatially_structured_networks.rst b/doc/htmldoc/networks/spatially_structured_networks.rst index c982239e53..198378b9c9 100644 --- a/doc/htmldoc/networks/spatially_structured_networks.rst +++ b/doc/htmldoc/networks/spatially_structured_networks.rst @@ -1516,7 +1516,6 @@ files for the ``Mask`` parent class: .. code:: c #include "mask.h" - #include "mask_impl.h" The ``Mask`` class has a few methods that must be overridden: diff --git a/libnestutil/dict_util.h b/libnestutil/dict_util.h index eeb954b5f9..93582046fe 100644 --- a/libnestutil/dict_util.h +++ b/libnestutil/dict_util.h @@ -25,8 +25,8 @@ // Includes from nestkernel: #include "kernel_manager.h" +#include "nest.h" #include "nest_datums.h" -#include "vp_manager_impl.h" // Includes from sli: #include "dictdatum.h" diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt index 4b861b13f3..3746c98cf0 100644 --- a/models/CMakeLists.txt +++ b/models/CMakeLists.txt @@ -23,10 +23,10 @@ set(models_sources weight_recorder.h weight_recorder.cpp # Required by CommonSynapseProperties cm_compartmentcurrents.h cm_compartmentcurrents.cpp cm_tree.h cm_tree.cpp - rate_neuron_ipn.h rate_neuron_ipn_impl.h - rate_neuron_opn.h rate_neuron_opn_impl.h - rate_transformer_node.h rate_transformer_node_impl.h - weight_optimizer.h weight_optimizer.cpp + rate_neuron_ipn.h + rate_neuron_opn.h + rate_transformer_node.h + weight_optimizer.h weight_optimizer.cpp ${MODELS_SOURCES_GENERATED} ) diff --git a/models/ac_generator.cpp b/models/ac_generator.cpp index d7c5ea7751..fe9d069e01 100644 --- a/models/ac_generator.cpp +++ b/models/ac_generator.cpp @@ -30,10 +30,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/aeif_cond_alpha.cpp b/models/aeif_cond_alpha.cpp index dc8298bc3e..94d8b19c9e 100644 --- a/models/aeif_cond_alpha.cpp +++ b/models/aeif_cond_alpha.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_cond_alpha_astro.cpp b/models/aeif_cond_alpha_astro.cpp index 9b073b5487..f6da7c1c6e 100644 --- a/models/aeif_cond_alpha_astro.cpp +++ b/models/aeif_cond_alpha_astro.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_cond_alpha_multisynapse.cpp b/models/aeif_cond_alpha_multisynapse.cpp index f027713973..64c2707926 100644 --- a/models/aeif_cond_alpha_multisynapse.cpp +++ b/models/aeif_cond_alpha_multisynapse.cpp @@ -34,8 +34,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/aeif_cond_beta_multisynapse.cpp b/models/aeif_cond_beta_multisynapse.cpp index 5ef7e10717..20646dc575 100644 --- a/models/aeif_cond_beta_multisynapse.cpp +++ b/models/aeif_cond_beta_multisynapse.cpp @@ -35,8 +35,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/aeif_cond_exp.cpp b/models/aeif_cond_exp.cpp index cb0eb86d0c..5fdcc39845 100644 --- a/models/aeif_cond_exp.cpp +++ b/models/aeif_cond_exp.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_psc_alpha.cpp b/models/aeif_psc_alpha.cpp index b4a1b9c86e..8a60a66f2d 100644 --- a/models/aeif_psc_alpha.cpp +++ b/models/aeif_psc_alpha.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_psc_delta.cpp b/models/aeif_psc_delta.cpp index 7cafe3ad64..c5762b8461 100644 --- a/models/aeif_psc_delta.cpp +++ b/models/aeif_psc_delta.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_psc_delta_clopath.cpp b/models/aeif_psc_delta_clopath.cpp index c45158ee77..3ef0c5747c 100644 --- a/models/aeif_psc_delta_clopath.cpp +++ b/models/aeif_psc_delta_clopath.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/aeif_psc_exp.cpp b/models/aeif_psc_exp.cpp index 6b8aec869c..3ea33218ef 100644 --- a/models/aeif_psc_exp.cpp +++ b/models/aeif_psc_exp.cpp @@ -37,9 +37,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "nest_names.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/amat2_psc_exp.cpp b/models/amat2_psc_exp.cpp index 06bce3bd22..cda1eab17c 100644 --- a/models/amat2_psc_exp.cpp +++ b/models/amat2_psc_exp.cpp @@ -30,8 +30,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/astrocyte_lr_1994.cpp b/models/astrocyte_lr_1994.cpp index cd32bf5bc5..d5fb3738e1 100644 --- a/models/astrocyte_lr_1994.cpp +++ b/models/astrocyte_lr_1994.cpp @@ -37,8 +37,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/bernoulli_synapse.cpp b/models/bernoulli_synapse.cpp index 95174cf2ef..06f354f196 100644 --- a/models/bernoulli_synapse.cpp +++ b/models/bernoulli_synapse.cpp @@ -22,9 +22,6 @@ #include "bernoulli_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_bernoulli_synapse( const std::string& name ) { diff --git a/models/binary_neuron.h b/models/binary_neuron.h index d3854d650e..d9afac52a7 100644 --- a/models/binary_neuron.h +++ b/models/binary_neuron.h @@ -35,7 +35,6 @@ #include "archiving_node.h" #include "connection.h" #include "event.h" -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" #include "nest_timeconverter.h" diff --git a/models/clopath_synapse.cpp b/models/clopath_synapse.cpp index 73a2cbd1fc..07af3f894d 100644 --- a/models/clopath_synapse.cpp +++ b/models/clopath_synapse.cpp @@ -22,9 +22,6 @@ #include "clopath_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_clopath_synapse( const std::string& name ) { diff --git a/models/cm_compartmentcurrents.h b/models/cm_compartmentcurrents.h index 87135ffe07..8153f1b290 100644 --- a/models/cm_compartmentcurrents.h +++ b/models/cm_compartmentcurrents.h @@ -24,6 +24,8 @@ #include +#include "logging.h" +#include "logging_manager.h" #include "ring_buffer.h" namespace nest diff --git a/models/cm_default.cpp b/models/cm_default.cpp index 37b714929b..d85159a1d4 100644 --- a/models/cm_default.cpp +++ b/models/cm_default.cpp @@ -22,9 +22,6 @@ #include "cm_default.h" -// Includes from nestkernel: -#include "nest_impl.h" - namespace nest { void diff --git a/models/cm_tree.cpp b/models/cm_tree.cpp index 52121ca2fe..dc85163687 100644 --- a/models/cm_tree.cpp +++ b/models/cm_tree.cpp @@ -21,6 +21,9 @@ */ #include "cm_tree.h" +#include "logging.h" +#include "logging_manager.h" + nest::Compartment::Compartment( const long compartment_index, const long parent_index ) : xx_( 0.0 ) diff --git a/models/cm_tree.h b/models/cm_tree.h index 6f5898729e..b4884eb5d2 100644 --- a/models/cm_tree.h +++ b/models/cm_tree.h @@ -38,7 +38,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/cont_delay_synapse.cpp b/models/cont_delay_synapse.cpp index a0a3e7afb7..6d37a6ee94 100644 --- a/models/cont_delay_synapse.cpp +++ b/models/cont_delay_synapse.cpp @@ -21,10 +21,6 @@ */ #include "cont_delay_synapse.h" -#include "cont_delay_synapse_impl.h" - -// Includes from nestkernel: -#include "nest_impl.h" void nest::register_cont_delay_synapse( const std::string& name ) diff --git a/models/cont_delay_synapse.h b/models/cont_delay_synapse.h index a5759c2622..057a69dcc8 100644 --- a/models/cont_delay_synapse.h +++ b/models/cont_delay_synapse.h @@ -248,6 +248,74 @@ cont_delay_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonS template < typename targetidentifierT > constexpr ConnectionModelProperties cont_delay_synapse< targetidentifierT >::properties; +template < typename targetidentifierT > +cont_delay_synapse< targetidentifierT >::cont_delay_synapse() + : ConnectionBase() + , weight_( 1.0 ) + , delay_offset_( 0.0 ) +{ +} + +template < typename targetidentifierT > +void +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< long >( d, names::size_of, sizeof( *this ) ); +} + +template < typename targetidentifierT > +void +cont_delay_synapse< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + ConnectionBase::set_status( d, cm ); + + updateValue< double >( d, names::weight, weight_ ); + + // set delay if mentioned + double delay; + + if ( updateValue< double >( d, names::delay, delay ) ) + { + + const double h = Time::get_resolution().get_ms(); + + double int_delay; + const double frac_delay = std::modf( delay / h, &int_delay ); + + if ( frac_delay == 0 ) + { + kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( delay ); + set_delay_steps( Time::delay_ms_to_steps( delay ) ); + delay_offset_ = 0.0; + } + else + { + const long lowerbound = static_cast< long >( int_delay ); + kernel().connection_manager.get_delay_checker().assert_two_valid_delays_steps( lowerbound, lowerbound + 1 ); + set_delay_steps( lowerbound + 1 ); + delay_offset_ = h * ( 1.0 - frac_delay ); + } + } +} + +template < typename targetidentifierT > +void +cont_delay_synapse< targetidentifierT >::check_synapse_params( const DictionaryDatum& syn_spec ) const +{ + if ( syn_spec->known( names::delay ) ) + { + LOG( M_WARNING, + "Connect", + "The delay will be rounded to the next multiple of the time step. " + "To use a more precise time delay it needs to be defined within " + "the synapse, e.g. with CopyModel()." ); + } +} + } // of namespace nest #endif // of #ifndef CONT_DELAY_SYNAPSE_H diff --git a/models/cont_delay_synapse_impl.h b/models/cont_delay_synapse_impl.h deleted file mode 100644 index 4a029b82a8..0000000000 --- a/models/cont_delay_synapse_impl.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * cont_delay_synapse_impl.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 CONT_DELAY_SYNAPSE_IMPL_H -#define CONT_DELAY_SYNAPSE_IMPL_H - -#include "cont_delay_synapse.h" - -// Includes from nestkernel: -#include "common_synapse_properties.h" -#include "connector_model.h" -#include "event.h" - -// Includes from sli: -#include "dictdatum.h" - -namespace nest -{ - -template < typename targetidentifierT > -cont_delay_synapse< targetidentifierT >::cont_delay_synapse() - : ConnectionBase() - , weight_( 1.0 ) - , delay_offset_( 0.0 ) -{ -} - -template < typename targetidentifierT > -void -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< long >( d, names::size_of, sizeof( *this ) ); -} - -template < typename targetidentifierT > -void -cont_delay_synapse< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) -{ - ConnectionBase::set_status( d, cm ); - - updateValue< double >( d, names::weight, weight_ ); - - // set delay if mentioned - double delay; - - if ( updateValue< double >( d, names::delay, delay ) ) - { - - const double h = Time::get_resolution().get_ms(); - - double int_delay; - const double frac_delay = std::modf( delay / h, &int_delay ); - - if ( frac_delay == 0 ) - { - kernel().connection_manager.get_delay_checker().assert_valid_delay_ms( delay ); - set_delay_steps( Time::delay_ms_to_steps( delay ) ); - delay_offset_ = 0.0; - } - else - { - const long lowerbound = static_cast< long >( int_delay ); - kernel().connection_manager.get_delay_checker().assert_two_valid_delays_steps( lowerbound, lowerbound + 1 ); - set_delay_steps( lowerbound + 1 ); - delay_offset_ = h * ( 1.0 - frac_delay ); - } - } -} - -template < typename targetidentifierT > -void -cont_delay_synapse< targetidentifierT >::check_synapse_params( const DictionaryDatum& syn_spec ) const -{ - if ( syn_spec->known( names::delay ) ) - { - LOG( M_WARNING, - "Connect", - "The delay will be rounded to the next multiple of the time step. " - "To use a more precise time delay it needs to be defined within " - "the synapse, e.g. with CopyModel()." ); - } -} - -} // of namespace nest - -#endif // #ifndef CONT_DELAY_SYNAPSE_IMPL_H diff --git a/models/correlation_detector.cpp b/models/correlation_detector.cpp index 3d7b09b8ae..9846ffac50 100644 --- a/models/correlation_detector.cpp +++ b/models/correlation_detector.cpp @@ -31,10 +31,6 @@ #include "dict_util.h" #include "logging.h" -// Includes from nestkernel: -#include "model_manager_impl.h" -#include "nest_impl.h" - // Includes from sli: #include "arraydatum.h" #include "dict.h" diff --git a/models/correlomatrix_detector.cpp b/models/correlomatrix_detector.cpp index bab3a03043..7fb08887c7 100644 --- a/models/correlomatrix_detector.cpp +++ b/models/correlomatrix_detector.cpp @@ -33,8 +33,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/correlospinmatrix_detector.cpp b/models/correlospinmatrix_detector.cpp index ec270da576..d49d82c0c3 100644 --- a/models/correlospinmatrix_detector.cpp +++ b/models/correlospinmatrix_detector.cpp @@ -33,8 +33,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/dc_generator.cpp b/models/dc_generator.cpp index 7c5389914f..606a7e2355 100644 --- a/models/dc_generator.cpp +++ b/models/dc_generator.cpp @@ -23,10 +23,7 @@ #include "dc_generator.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from libnestutil: #include "dict_util.h" diff --git a/models/diffusion_connection.cpp b/models/diffusion_connection.cpp index bd23f5dfe1..9bfd6f6449 100644 --- a/models/diffusion_connection.cpp +++ b/models/diffusion_connection.cpp @@ -22,9 +22,6 @@ #include "diffusion_connection.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_diffusion_connection( const std::string& name ) { diff --git a/models/eprop_iaf.cpp b/models/eprop_iaf.cpp index fb336a40f4..adf74577af 100644 --- a/models/eprop_iaf.cpp +++ b/models/eprop_iaf.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf.h b/models/eprop_iaf.h index 225de65333..a9966fd16a 100644 --- a/models/eprop_iaf.h +++ b/models/eprop_iaf.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "eprop_synapse.h" #include "event.h" diff --git a/models/eprop_iaf_adapt.cpp b/models/eprop_iaf_adapt.cpp index 10cb9ff224..7f52ed0554 100644 --- a/models/eprop_iaf_adapt.cpp +++ b/models/eprop_iaf_adapt.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf_adapt.h b/models/eprop_iaf_adapt.h index d404dcbd69..e6f1976fe6 100644 --- a/models/eprop_iaf_adapt.h +++ b/models/eprop_iaf_adapt.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "eprop_synapse.h" #include "event.h" diff --git a/models/eprop_iaf_adapt_bsshslm_2020.cpp b/models/eprop_iaf_adapt_bsshslm_2020.cpp index f37f2203a0..b665212e0c 100644 --- a/models/eprop_iaf_adapt_bsshslm_2020.cpp +++ b/models/eprop_iaf_adapt_bsshslm_2020.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf_adapt_bsshslm_2020.h b/models/eprop_iaf_adapt_bsshslm_2020.h index f8d8009ba2..844ca7cf3c 100644 --- a/models/eprop_iaf_adapt_bsshslm_2020.h +++ b/models/eprop_iaf_adapt_bsshslm_2020.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "event.h" #include "nest_types.h" diff --git a/models/eprop_iaf_bsshslm_2020.cpp b/models/eprop_iaf_bsshslm_2020.cpp index a4c52557ff..2a6a4f9aac 100644 --- a/models/eprop_iaf_bsshslm_2020.cpp +++ b/models/eprop_iaf_bsshslm_2020.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf_bsshslm_2020.h b/models/eprop_iaf_bsshslm_2020.h index 34cc9a575d..1eca5799a7 100644 --- a/models/eprop_iaf_bsshslm_2020.h +++ b/models/eprop_iaf_bsshslm_2020.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "event.h" #include "nest_types.h" diff --git a/models/eprop_iaf_psc_delta.cpp b/models/eprop_iaf_psc_delta.cpp index a8b13ac4e4..bcc83788b5 100644 --- a/models/eprop_iaf_psc_delta.cpp +++ b/models/eprop_iaf_psc_delta.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf_psc_delta.h b/models/eprop_iaf_psc_delta.h index c36066a984..60a7ee4235 100644 --- a/models/eprop_iaf_psc_delta.h +++ b/models/eprop_iaf_psc_delta.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "eprop_synapse.h" #include "event.h" diff --git a/models/eprop_iaf_psc_delta_adapt.cpp b/models/eprop_iaf_psc_delta_adapt.cpp index 9ffe2a8b69..f720140773 100644 --- a/models/eprop_iaf_psc_delta_adapt.cpp +++ b/models/eprop_iaf_psc_delta_adapt.cpp @@ -31,11 +31,8 @@ #include "numerics.h" // nestkernel -#include "eprop_archiving_node_recurrent_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_iaf_psc_delta_adapt.h b/models/eprop_iaf_psc_delta_adapt.h index 3c0949de3a..50d65bae46 100644 --- a/models/eprop_iaf_psc_delta_adapt.h +++ b/models/eprop_iaf_psc_delta_adapt.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_recurrent.h" #include "eprop_synapse.h" #include "event.h" diff --git a/models/eprop_learning_signal_connection.cpp b/models/eprop_learning_signal_connection.cpp index 7e537ed5c0..38230ac394 100644 --- a/models/eprop_learning_signal_connection.cpp +++ b/models/eprop_learning_signal_connection.cpp @@ -23,7 +23,6 @@ #include "eprop_learning_signal_connection.h" // nestkernel -#include "nest_impl.h" void nest::register_eprop_learning_signal_connection( const std::string& name ) diff --git a/models/eprop_learning_signal_connection_bsshslm_2020.cpp b/models/eprop_learning_signal_connection_bsshslm_2020.cpp index fe29c2a84c..b5477ef5ec 100644 --- a/models/eprop_learning_signal_connection_bsshslm_2020.cpp +++ b/models/eprop_learning_signal_connection_bsshslm_2020.cpp @@ -23,7 +23,6 @@ #include "eprop_learning_signal_connection_bsshslm_2020.h" // nestkernel -#include "nest_impl.h" void nest::register_eprop_learning_signal_connection_bsshslm_2020( const std::string& name ) diff --git a/models/eprop_readout.cpp b/models/eprop_readout.cpp index b2f740d70e..66011a4d60 100644 --- a/models/eprop_readout.cpp +++ b/models/eprop_readout.cpp @@ -33,8 +33,6 @@ // nestkernel #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_readout.h b/models/eprop_readout.h index b96c007542..edaa2ae39b 100644 --- a/models/eprop_readout.h +++ b/models/eprop_readout.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_readout.h" #include "eprop_synapse.h" #include "event.h" diff --git a/models/eprop_readout_bsshslm_2020.cpp b/models/eprop_readout_bsshslm_2020.cpp index 79f059fb59..f2e903aa2b 100644 --- a/models/eprop_readout_bsshslm_2020.cpp +++ b/models/eprop_readout_bsshslm_2020.cpp @@ -33,8 +33,6 @@ // nestkernel #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // sli #include "dictutils.h" diff --git a/models/eprop_readout_bsshslm_2020.h b/models/eprop_readout_bsshslm_2020.h index 36ae6e7134..38e5ac95be 100644 --- a/models/eprop_readout_bsshslm_2020.h +++ b/models/eprop_readout_bsshslm_2020.h @@ -25,7 +25,6 @@ // nestkernel #include "connection.h" -#include "eprop_archiving_node_impl.h" #include "eprop_archiving_node_readout.h" #include "event.h" #include "nest_types.h" diff --git a/models/eprop_synapse.cpp b/models/eprop_synapse.cpp index f167592024..59b8c40fba 100644 --- a/models/eprop_synapse.cpp +++ b/models/eprop_synapse.cpp @@ -23,7 +23,6 @@ #include "eprop_synapse.h" // nestkernel -#include "nest_impl.h" namespace nest { diff --git a/models/eprop_synapse_bsshslm_2020.cpp b/models/eprop_synapse_bsshslm_2020.cpp index ceb1dba4d1..de41bd993f 100644 --- a/models/eprop_synapse_bsshslm_2020.cpp +++ b/models/eprop_synapse_bsshslm_2020.cpp @@ -23,7 +23,6 @@ #include "eprop_synapse_bsshslm_2020.h" // nestkernel -#include "nest_impl.h" namespace nest { diff --git a/models/erfc_neuron.cpp b/models/erfc_neuron.cpp index 891a7cfc1f..ec25c34c05 100644 --- a/models/erfc_neuron.cpp +++ b/models/erfc_neuron.cpp @@ -24,9 +24,6 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" namespace nest { diff --git a/models/gamma_sup_generator.cpp b/models/gamma_sup_generator.cpp index 5817c36f7f..96c59098a4 100644 --- a/models/gamma_sup_generator.cpp +++ b/models/gamma_sup_generator.cpp @@ -22,17 +22,12 @@ #include "gamma_sup_generator.h" -// C++ includes: -#include - // Includes from libnestutil: #include "dict_util.h" -#include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/gap_junction.cpp b/models/gap_junction.cpp index 4dd0886c6c..63fce5f4f4 100644 --- a/models/gap_junction.cpp +++ b/models/gap_junction.cpp @@ -22,9 +22,6 @@ #include "gap_junction.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_gap_junction( const std::string& name ) { diff --git a/models/gauss_rate.cpp b/models/gauss_rate.cpp index 520f0228e9..6a68d8357a 100644 --- a/models/gauss_rate.cpp +++ b/models/gauss_rate.cpp @@ -24,8 +24,6 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" namespace nest { diff --git a/models/gauss_rate.h b/models/gauss_rate.h index 8d51447775..71cdee6f50 100644 --- a/models/gauss_rate.h +++ b/models/gauss_rate.h @@ -28,9 +28,7 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" // Includes from libnestutil: #include "dict_util.h" diff --git a/models/gif_cond_exp.cpp b/models/gif_cond_exp.cpp index 43e7d96d19..9bb5ef88c4 100644 --- a/models/gif_cond_exp.cpp +++ b/models/gif_cond_exp.cpp @@ -35,8 +35,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/gif_cond_exp_multisynapse.cpp b/models/gif_cond_exp_multisynapse.cpp index 5a31ba490f..d3921d7484 100644 --- a/models/gif_cond_exp_multisynapse.cpp +++ b/models/gif_cond_exp_multisynapse.cpp @@ -36,8 +36,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/gif_pop_psc_exp.cpp b/models/gif_pop_psc_exp.cpp index 43299c877f..32e3ffabb0 100644 --- a/models/gif_pop_psc_exp.cpp +++ b/models/gif_pop_psc_exp.cpp @@ -37,12 +37,6 @@ #include "compose.hpp" #include "dict_util.h" -// Includes from nestkernel: -#include "model_manager_impl.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" - - #ifdef HAVE_GSL namespace nest diff --git a/models/gif_psc_exp.cpp b/models/gif_psc_exp.cpp index 0731dc8175..fd6c5ca2eb 100644 --- a/models/gif_psc_exp.cpp +++ b/models/gif_psc_exp.cpp @@ -23,10 +23,10 @@ #include "gif_psc_exp.h" // Includes from nestkernel: +#include "compose.hpp" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" +#include "numerics.h" // Includes from libnestutil: #include "dict_util.h" @@ -36,9 +36,6 @@ #include "dict.h" #include "dictutils.h" -#include "compose.hpp" -#include "numerics.h" - namespace nest { void diff --git a/models/gif_psc_exp_multisynapse.cpp b/models/gif_psc_exp_multisynapse.cpp index cfeca96ea4..8502c0db22 100644 --- a/models/gif_psc_exp_multisynapse.cpp +++ b/models/gif_psc_exp_multisynapse.cpp @@ -30,8 +30,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/ginzburg_neuron.cpp b/models/ginzburg_neuron.cpp index 36b94176cb..0c331630f4 100644 --- a/models/ginzburg_neuron.cpp +++ b/models/ginzburg_neuron.cpp @@ -24,9 +24,6 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" namespace nest { diff --git a/models/glif_cond.cpp b/models/glif_cond.cpp index a1434786b9..3592cc281e 100644 --- a/models/glif_cond.cpp +++ b/models/glif_cond.cpp @@ -36,8 +36,6 @@ #include "exceptions.h" #include "kernel_manager.h" #include "name.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" @@ -802,8 +800,8 @@ nest::glif_cond::handle( CurrentEvent& e ) e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); } -// Do not move this function as inline to h-file. It depends on -// universal_data_logger_impl.h being included here. +// TODO JV +// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. void nest::glif_cond::handle( DataLoggingRequest& e ) { diff --git a/models/glif_psc.cpp b/models/glif_psc.cpp index b60dafc0ec..c0844856c3 100644 --- a/models/glif_psc.cpp +++ b/models/glif_psc.cpp @@ -31,8 +31,6 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" @@ -627,11 +625,3 @@ nest::glif_psc::handle( CurrentEvent& e ) B_.currents_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); } - -// Do not move this function as inline to h-file. It depends on -// universal_data_logger_impl.h being included here. -void -nest::glif_psc::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); // the logger does this for us -} diff --git a/models/glif_psc.h b/models/glif_psc.h index 63d51b93e8..d07e3a60aa 100644 --- a/models/glif_psc.h +++ b/models/glif_psc.h @@ -461,6 +461,12 @@ glif_psc::set_status( const DictionaryDatum& d ) S_ = stmp; } +void +nest::glif_psc::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); // the logger does this for us +} + } // namespace nest #endif diff --git a/models/glif_psc_double_alpha.cpp b/models/glif_psc_double_alpha.cpp index f79de012d3..c7168ae582 100644 --- a/models/glif_psc_double_alpha.cpp +++ b/models/glif_psc_double_alpha.cpp @@ -31,8 +31,6 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" @@ -698,8 +696,8 @@ nest::glif_psc_double_alpha::handle( CurrentEvent& e ) e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); } -// Do not move this function as inline to h-file. It depends on -// universal_data_logger_impl.h being included here. +// TODO JV +// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. void nest::glif_psc_double_alpha::handle( DataLoggingRequest& e ) { diff --git a/models/hh_cond_beta_gap_traub.cpp b/models/hh_cond_beta_gap_traub.cpp index 7907b051c8..958b3396c7 100644 --- a/models/hh_cond_beta_gap_traub.cpp +++ b/models/hh_cond_beta_gap_traub.cpp @@ -41,8 +41,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/hh_cond_exp_traub.cpp b/models/hh_cond_exp_traub.cpp index 5aa908a15d..86aae90aba 100644 --- a/models/hh_cond_exp_traub.cpp +++ b/models/hh_cond_exp_traub.cpp @@ -38,8 +38,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/hh_psc_alpha.cpp b/models/hh_psc_alpha.cpp index 29e953b810..d80b410956 100644 --- a/models/hh_psc_alpha.cpp +++ b/models/hh_psc_alpha.cpp @@ -33,11 +33,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/hh_psc_alpha_clopath.cpp b/models/hh_psc_alpha_clopath.cpp index e0c35e830f..287f8ec5c6 100644 --- a/models/hh_psc_alpha_clopath.cpp +++ b/models/hh_psc_alpha_clopath.cpp @@ -33,11 +33,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/hh_psc_alpha_gap.cpp b/models/hh_psc_alpha_gap.cpp index b26176784f..10076c0507 100644 --- a/models/hh_psc_alpha_gap.cpp +++ b/models/hh_psc_alpha_gap.cpp @@ -37,8 +37,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/ht_neuron.cpp b/models/ht_neuron.cpp index 047ca61fa3..48bf8575a6 100644 --- a/models/ht_neuron.cpp +++ b/models/ht_neuron.cpp @@ -33,8 +33,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" namespace nest { diff --git a/models/ht_synapse.cpp b/models/ht_synapse.cpp index b92c297138..968e4fb785 100644 --- a/models/ht_synapse.cpp +++ b/models/ht_synapse.cpp @@ -22,9 +22,6 @@ #include "ht_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_ht_synapse( const std::string& name ) { diff --git a/models/iaf_bw_2001.cpp b/models/iaf_bw_2001.cpp index e030579183..34c4ce0974 100644 --- a/models/iaf_bw_2001.cpp +++ b/models/iaf_bw_2001.cpp @@ -33,8 +33,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" @@ -486,8 +484,8 @@ nest::iaf_bw_2001::update( Time const& origin, const long from, const long to ) } } -// Do not move this function as inline to h-file. It depends on -// universal_data_logger_impl.h being included here. +// TODO JV +// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. void nest::iaf_bw_2001::handle( DataLoggingRequest& e ) { diff --git a/models/iaf_bw_2001_exact.cpp b/models/iaf_bw_2001_exact.cpp index 3855c27a53..537a21e325 100644 --- a/models/iaf_bw_2001_exact.cpp +++ b/models/iaf_bw_2001_exact.cpp @@ -32,8 +32,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" @@ -517,8 +515,8 @@ nest::iaf_bw_2001_exact::update( Time const& origin, const long from, const long } } -// Do not move this function as inline to h-file. It depends on -// universal_data_logger_impl.h being included here. +// TODO JV +// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. void nest::iaf_bw_2001_exact::handle( DataLoggingRequest& e ) { diff --git a/models/iaf_chs_2007.cpp b/models/iaf_chs_2007.cpp index b5c183d7b0..e947b03bef 100644 --- a/models/iaf_chs_2007.cpp +++ b/models/iaf_chs_2007.cpp @@ -29,8 +29,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/iaf_chxk_2008.cpp b/models/iaf_chxk_2008.cpp index 62559536ae..fb847e3d8e 100644 --- a/models/iaf_chxk_2008.cpp +++ b/models/iaf_chxk_2008.cpp @@ -34,8 +34,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_cond_alpha.cpp b/models/iaf_cond_alpha.cpp index 7cbff968ee..ff30457d89 100644 --- a/models/iaf_cond_alpha.cpp +++ b/models/iaf_cond_alpha.cpp @@ -36,8 +36,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_cond_alpha_mc.cpp b/models/iaf_cond_alpha_mc.cpp index 2b99b81025..711bf921f2 100644 --- a/models/iaf_cond_alpha_mc.cpp +++ b/models/iaf_cond_alpha_mc.cpp @@ -36,8 +36,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/iaf_cond_beta.cpp b/models/iaf_cond_beta.cpp index a0f5d59c2e..8a1a537b69 100644 --- a/models/iaf_cond_beta.cpp +++ b/models/iaf_cond_beta.cpp @@ -37,8 +37,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_cond_exp.cpp b/models/iaf_cond_exp.cpp index c777d686fd..860853d149 100644 --- a/models/iaf_cond_exp.cpp +++ b/models/iaf_cond_exp.cpp @@ -36,8 +36,6 @@ #include "event.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_cond_exp_sfa_rr.cpp b/models/iaf_cond_exp_sfa_rr.cpp index d37b461e06..96c3d66f58 100644 --- a/models/iaf_cond_exp_sfa_rr.cpp +++ b/models/iaf_cond_exp_sfa_rr.cpp @@ -36,8 +36,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_alpha.cpp b/models/iaf_psc_alpha.cpp index 053a30a22c..1ea6ce344e 100644 --- a/models/iaf_psc_alpha.cpp +++ b/models/iaf_psc_alpha.cpp @@ -30,10 +30,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "ring_buffer_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_alpha_multisynapse.cpp b/models/iaf_psc_alpha_multisynapse.cpp index cee69d2889..5a55757292 100644 --- a/models/iaf_psc_alpha_multisynapse.cpp +++ b/models/iaf_psc_alpha_multisynapse.cpp @@ -30,9 +30,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/iaf_psc_alpha_ps.cpp b/models/iaf_psc_alpha_ps.cpp index 885d1f2051..cf040eb540 100644 --- a/models/iaf_psc_alpha_ps.cpp +++ b/models/iaf_psc_alpha_ps.cpp @@ -34,8 +34,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_delta.cpp b/models/iaf_psc_delta.cpp index 4de329ed60..4d405c18e2 100644 --- a/models/iaf_psc_delta.cpp +++ b/models/iaf_psc_delta.cpp @@ -34,8 +34,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_delta_ps.cpp b/models/iaf_psc_delta_ps.cpp index 1da42f3dcc..513715967c 100644 --- a/models/iaf_psc_delta_ps.cpp +++ b/models/iaf_psc_delta_ps.cpp @@ -35,8 +35,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_exp.cpp b/models/iaf_psc_exp.cpp index 48385040db..e6b3a61e55 100644 --- a/models/iaf_psc_exp.cpp +++ b/models/iaf_psc_exp.cpp @@ -32,10 +32,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "ring_buffer_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_exp_htum.cpp b/models/iaf_psc_exp_htum.cpp index dd38c565cd..85d430b38f 100644 --- a/models/iaf_psc_exp_htum.cpp +++ b/models/iaf_psc_exp_htum.cpp @@ -28,9 +28,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_exp_multisynapse.cpp b/models/iaf_psc_exp_multisynapse.cpp index 7c53921537..3d39df7889 100644 --- a/models/iaf_psc_exp_multisynapse.cpp +++ b/models/iaf_psc_exp_multisynapse.cpp @@ -27,9 +27,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/iaf_psc_exp_ps.cpp b/models/iaf_psc_exp_ps.cpp index 71f83acc78..109861db27 100644 --- a/models/iaf_psc_exp_ps.cpp +++ b/models/iaf_psc_exp_ps.cpp @@ -34,8 +34,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/iaf_psc_exp_ps_lossless.cpp b/models/iaf_psc_exp_ps_lossless.cpp index dcbf6435bf..9561747875 100644 --- a/models/iaf_psc_exp_ps_lossless.cpp +++ b/models/iaf_psc_exp_ps_lossless.cpp @@ -27,8 +27,6 @@ // Includes from nestkernel: #include "exceptions.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from libnestutil: #include "dict_util.h" diff --git a/models/iaf_tum_2000.cpp b/models/iaf_tum_2000.cpp index 29ae084558..b1510bf0fe 100644 --- a/models/iaf_tum_2000.cpp +++ b/models/iaf_tum_2000.cpp @@ -31,10 +31,7 @@ #include "exceptions.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "nest_impl.h" #include "numerics.h" -#include "ring_buffer_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/ignore_and_fire.cpp b/models/ignore_and_fire.cpp index 82b61785da..5e6368bebf 100644 --- a/models/ignore_and_fire.cpp +++ b/models/ignore_and_fire.cpp @@ -27,15 +27,11 @@ // Includes from nestkernel: #include "exceptions.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from libnestutil: #include "dict_util.h" #include "iaf_propagator.h" #include "kernel_manager.h" -#include "numerics.h" -#include "ring_buffer_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/ignore_and_fire.h b/models/ignore_and_fire.h index 857e596ce9..b74ea3a7a4 100644 --- a/models/ignore_and_fire.h +++ b/models/ignore_and_fire.h @@ -116,24 +116,24 @@ class ignore_and_fire : public ArchivingNode using Node::handle; using Node::handles_test_event; - size_t send_test_event( Node&, size_t, synindex, bool ); + size_t send_test_event( Node&, size_t, synindex, bool ) override; - void handle( SpikeEvent& ); - void handle( CurrentEvent& ); - void handle( DataLoggingRequest& ); + void handle( SpikeEvent& ) override; + void handle( CurrentEvent& ) override; + void handle( DataLoggingRequest& ) override; - size_t handles_test_event( SpikeEvent&, size_t ); - size_t handles_test_event( CurrentEvent&, size_t ); - size_t handles_test_event( DataLoggingRequest&, size_t ); + size_t handles_test_event( SpikeEvent&, size_t ) override; + size_t handles_test_event( CurrentEvent&, size_t ) override; + size_t handles_test_event( DataLoggingRequest&, size_t ) override; - void get_status( DictionaryDatum& ) const; - void set_status( const DictionaryDatum& ); + void get_status( DictionaryDatum& ) const override; + void set_status( const DictionaryDatum& ) override; private: - void init_buffers_(); - void pre_run_hook(); + void init_buffers_() override; + void pre_run_hook() override; - void update( Time const&, const long, const long ); + void update( Time const&, const long, const long ) override; // The next two classes need to be friends to access the State_ class/member friend class RecordablesMap< ignore_and_fire >; diff --git a/models/inhomogeneous_poisson_generator.cpp b/models/inhomogeneous_poisson_generator.cpp index 8f0b5f58ba..cb5459ea3c 100644 --- a/models/inhomogeneous_poisson_generator.cpp +++ b/models/inhomogeneous_poisson_generator.cpp @@ -29,11 +29,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/izhikevich.cpp b/models/izhikevich.cpp index 9865f74427..71558f17e3 100644 --- a/models/izhikevich.cpp +++ b/models/izhikevich.cpp @@ -30,11 +30,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/jonke_synapse.cpp b/models/jonke_synapse.cpp index 3aea1fb292..532ecf40cb 100644 --- a/models/jonke_synapse.cpp +++ b/models/jonke_synapse.cpp @@ -22,9 +22,6 @@ #include "jonke_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_jonke_synapse( const std::string& name ) { diff --git a/models/lin_rate.cpp b/models/lin_rate.cpp index 2db3fcafd1..2c524a2afd 100644 --- a/models/lin_rate.cpp +++ b/models/lin_rate.cpp @@ -24,8 +24,8 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" + +#include namespace nest { diff --git a/models/lin_rate.h b/models/lin_rate.h index 5482c62aae..e11e025c0e 100644 --- a/models/lin_rate.h +++ b/models/lin_rate.h @@ -25,11 +25,8 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_neuron_opn.h" -#include "rate_neuron_opn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" namespace nest { diff --git a/models/mat2_psc_exp.cpp b/models/mat2_psc_exp.cpp index 104d20af0f..2c42c5a458 100644 --- a/models/mat2_psc_exp.cpp +++ b/models/mat2_psc_exp.cpp @@ -30,8 +30,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/mcculloch_pitts_neuron.cpp b/models/mcculloch_pitts_neuron.cpp index 2f8b15a6d9..9032171e44 100644 --- a/models/mcculloch_pitts_neuron.cpp +++ b/models/mcculloch_pitts_neuron.cpp @@ -24,9 +24,6 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" namespace nest { diff --git a/models/mip_generator.cpp b/models/mip_generator.cpp index bf60516e97..03ce07134e 100644 --- a/models/mip_generator.cpp +++ b/models/mip_generator.cpp @@ -27,10 +27,9 @@ #include "dict_util.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" void nest::register_mip_generator( const std::string& name ) diff --git a/models/multimeter.cpp b/models/multimeter.cpp index 2943c45850..1318dad50a 100644 --- a/models/multimeter.cpp +++ b/models/multimeter.cpp @@ -22,13 +22,9 @@ #include "multimeter.h" -// Includes from nestkernel: -#include "event_delivery_manager_impl.h" -#include "model_manager_impl.h" -#include "nest_impl.h" - // Includes from libnestutil: #include "dict_util.h" +#include "event_delivery_manager.h" namespace nest { diff --git a/models/music_cont_in_proxy.cpp b/models/music_cont_in_proxy.cpp index b0301aa8e4..41dbb9269a 100644 --- a/models/music_cont_in_proxy.cpp +++ b/models/music_cont_in_proxy.cpp @@ -38,7 +38,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "nest_impl.h" void nest::register_music_cont_in_proxy( const std::string& name ) diff --git a/models/music_cont_out_proxy.cpp b/models/music_cont_out_proxy.cpp index a3d57d4f58..1eef0f015c 100644 --- a/models/music_cont_out_proxy.cpp +++ b/models/music_cont_out_proxy.cpp @@ -29,10 +29,8 @@ #include // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" #include "nest_datums.h" -#include "nest_impl.h" // Includes from libnestutil: #include "compose.hpp" diff --git a/models/music_event_in_proxy.cpp b/models/music_event_in_proxy.cpp index 331d195f46..7e182c0dcc 100644 --- a/models/music_event_in_proxy.cpp +++ b/models/music_event_in_proxy.cpp @@ -31,17 +31,10 @@ #include "arraydatum.h" #include "dict.h" #include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" - -// Includes from libnestutil: -#include "compose.hpp" -#include "logging.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" +#include "music_manager.h" void nest::register_music_event_in_proxy( const std::string& name ) diff --git a/models/music_event_out_proxy.cpp b/models/music_event_out_proxy.cpp index 7c30ccd47d..34e6c5094c 100644 --- a/models/music_event_out_proxy.cpp +++ b/models/music_event_out_proxy.cpp @@ -31,7 +31,6 @@ #include "arraydatum.h" #include "dict.h" #include "dictutils.h" -#include "doubledatum.h" #include "integerdatum.h" // Includes from libnestutil: @@ -40,7 +39,8 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "nest_impl.h" +#include "music_manager.h" +#include "nest.h" void nest::register_music_event_out_proxy( const std::string& name ) diff --git a/models/music_message_in_proxy.cpp b/models/music_message_in_proxy.cpp index b0b7aa4f82..fd58c5947b 100644 --- a/models/music_message_in_proxy.cpp +++ b/models/music_message_in_proxy.cpp @@ -38,7 +38,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "nest_impl.h" void nest::register_music_message_in_proxy( const std::string& name ) diff --git a/models/music_rate_in_proxy.cpp b/models/music_rate_in_proxy.cpp index 20f6a23dd9..70028f3f9f 100644 --- a/models/music_rate_in_proxy.cpp +++ b/models/music_rate_in_proxy.cpp @@ -36,9 +36,7 @@ #include "logging.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" void nest::register_music_rate_in_proxy( const std::string& name ) diff --git a/models/music_rate_out_proxy.cpp b/models/music_rate_out_proxy.cpp index 9753421447..e12631a0ef 100644 --- a/models/music_rate_out_proxy.cpp +++ b/models/music_rate_out_proxy.cpp @@ -40,7 +40,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "nest_impl.h" /* ---------------------------------------------------------------- * Default constructors defining default parameters and state diff --git a/models/noise_generator.cpp b/models/noise_generator.cpp index 7bc72369da..6f9fa3795c 100644 --- a/models/noise_generator.cpp +++ b/models/noise_generator.cpp @@ -29,10 +29,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/noise_generator.h b/models/noise_generator.h index 8f73511ae3..e928af53ff 100644 --- a/models/noise_generator.h +++ b/models/noise_generator.h @@ -28,9 +28,7 @@ // Includes from nestkernel: #include "connection.h" -#include "device_node.h" #include "event.h" -#include "nest_timeconverter.h" #include "nest_types.h" #include "random_generators.h" #include "stimulation_device.h" diff --git a/models/parrot_neuron.cpp b/models/parrot_neuron.cpp index 6009758f02..961685dd72 100644 --- a/models/parrot_neuron.cpp +++ b/models/parrot_neuron.cpp @@ -23,17 +23,8 @@ #include "parrot_neuron.h" -// Includes from libnestutil: -#include "numerics.h" - // Includes from nestkernel: -#include "event_delivery_manager_impl.h" -#include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" - -// Includes from sli: -#include "dictutils.h" namespace nest { diff --git a/models/parrot_neuron_ps.cpp b/models/parrot_neuron_ps.cpp index 18140972a8..79eddaae4c 100644 --- a/models/parrot_neuron_ps.cpp +++ b/models/parrot_neuron_ps.cpp @@ -26,10 +26,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/models/poisson_generator.cpp b/models/poisson_generator.cpp index 516a886bca..e1de8bfe10 100644 --- a/models/poisson_generator.cpp +++ b/models/poisson_generator.cpp @@ -23,10 +23,9 @@ #include "poisson_generator.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from libnestutil: #include "dict_util.h" diff --git a/models/poisson_generator_ps.cpp b/models/poisson_generator_ps.cpp index 7a913d15bc..830d558c28 100644 --- a/models/poisson_generator_ps.cpp +++ b/models/poisson_generator_ps.cpp @@ -27,12 +27,11 @@ #include // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from libnestutil: #include "dict_util.h" +#include "event_delivery_manager.h" // Includes from sli: #include "dict.h" diff --git a/models/pp_cond_exp_mc_urbanczik.cpp b/models/pp_cond_exp_mc_urbanczik.cpp index 04d58df15f..fc6c477902 100644 --- a/models/pp_cond_exp_mc_urbanczik.cpp +++ b/models/pp_cond_exp_mc_urbanczik.cpp @@ -35,9 +35,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/pp_cond_exp_mc_urbanczik.h b/models/pp_cond_exp_mc_urbanczik.h index 9a109247bb..8258549a1c 100644 --- a/models/pp_cond_exp_mc_urbanczik.h +++ b/models/pp_cond_exp_mc_urbanczik.h @@ -45,7 +45,6 @@ #include "ring_buffer.h" #include "universal_data_logger.h" #include "urbanczik_archiving_node.h" -#include "urbanczik_archiving_node_impl.h" // Includes from sli: #include "dictdatum.h" diff --git a/models/pp_psc_delta.cpp b/models/pp_psc_delta.cpp index 482fde1dff..96161ecb40 100644 --- a/models/pp_psc_delta.cpp +++ b/models/pp_psc_delta.cpp @@ -36,8 +36,6 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/ppd_sup_generator.cpp b/models/ppd_sup_generator.cpp index 32eb092145..5dddb142fb 100644 --- a/models/ppd_sup_generator.cpp +++ b/models/ppd_sup_generator.cpp @@ -30,9 +30,8 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/pulsepacket_generator.cpp b/models/pulsepacket_generator.cpp index 19b4db16c6..dfe2391dee 100644 --- a/models/pulsepacket_generator.cpp +++ b/models/pulsepacket_generator.cpp @@ -27,13 +27,11 @@ // Includes from libnestutil: #include "dict_util.h" -#include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/quantal_stp_synapse.cpp b/models/quantal_stp_synapse.cpp index 829579605f..d0d4be6946 100644 --- a/models/quantal_stp_synapse.cpp +++ b/models/quantal_stp_synapse.cpp @@ -21,10 +21,6 @@ */ #include "quantal_stp_synapse.h" -#include "quantal_stp_synapse_impl.h" - -// Includes from nestkernel: -#include "nest_impl.h" void nest::register_quantal_stp_synapse( const std::string& name ) diff --git a/models/quantal_stp_synapse.h b/models/quantal_stp_synapse.h index 41b2fbf51d..79f4892a12 100644 --- a/models/quantal_stp_synapse.h +++ b/models/quantal_stp_synapse.h @@ -259,6 +259,70 @@ quantal_stp_synapse< targetidentifierT >::send( Event& e, size_t t, const Common return send_spike; } +template < typename targetidentifierT > +quantal_stp_synapse< targetidentifierT >::quantal_stp_synapse() + : ConnectionBase() + , weight_( 1.0 ) + , U_( 0.5 ) + , u_( U_ ) + , tau_rec_( 800.0 ) + , tau_fac_( 0.0 ) + , n_( 1 ) + , a_( n_ ) + , t_lastspike_( -1.0 ) +{ +} + +template < typename targetidentifierT > +void +quantal_stp_synapse< targetidentifierT >::get_status( DictionaryDatum& d ) const +{ + ConnectionBase::get_status( d ); + def< double >( d, names::weight, weight_ ); + def< double >( d, names::dU, U_ ); + def< double >( d, names::u, u_ ); + def< double >( d, names::tau_rec, tau_rec_ ); + def< double >( d, names::tau_fac, tau_fac_ ); + def< int >( d, names::n, n_ ); + def< int >( d, names::a, a_ ); +} + + +template < typename targetidentifierT > +void +quantal_stp_synapse< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + ConnectionBase::set_status( d, cm ); + updateValue< double >( d, names::weight, weight_ ); + + updateValue< double >( d, names::dU, U_ ); + if ( U_ > 1.0 or U_ < 0.0 ) + { + throw BadProperty( "'U' must be in [0,1]." ); + } + + updateValue< double >( d, names::u, u_ ); + if ( u_ > 1.0 or u_ < 0.0 ) + { + throw BadProperty( "'u' must be in [0,1]." ); + } + + updateValue< double >( d, names::tau_rec, tau_rec_ ); + if ( tau_rec_ <= 0.0 ) + { + throw BadProperty( "'tau_rec' must be > 0." ); + } + + updateValue< double >( d, names::tau_fac, tau_fac_ ); + if ( tau_fac_ < 0.0 ) + { + throw BadProperty( "'tau_fac' must be >= 0." ); + } + + updateValue< long >( d, names::n, n_ ); + updateValue< long >( d, names::a, a_ ); +} + } // namespace #endif // QUANTAL_STP_SYNAPSE_H diff --git a/models/quantal_stp_synapse_impl.h b/models/quantal_stp_synapse_impl.h index 1df262df46..e69de29bb2 100644 --- a/models/quantal_stp_synapse_impl.h +++ b/models/quantal_stp_synapse_impl.h @@ -1,105 +0,0 @@ -/* - * quantal_stp_synapse_impl.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 QUANTAL_STP_SYNAPSE_IMPL_H -#define QUANTAL_STP_SYNAPSE_IMPL_H - -#include "quantal_stp_synapse.h" - -// Includes from nestkernel: -#include "connection.h" -#include "connector_model.h" -#include "nest_names.h" - -// Includes from sli: -#include "dictutils.h" - -namespace nest -{ - -template < typename targetidentifierT > -quantal_stp_synapse< targetidentifierT >::quantal_stp_synapse() - : ConnectionBase() - , weight_( 1.0 ) - , U_( 0.5 ) - , u_( U_ ) - , tau_rec_( 800.0 ) - , tau_fac_( 0.0 ) - , n_( 1 ) - , a_( n_ ) - , t_lastspike_( -1.0 ) -{ -} - -template < typename targetidentifierT > -void -quantal_stp_synapse< targetidentifierT >::get_status( DictionaryDatum& d ) const -{ - ConnectionBase::get_status( d ); - def< double >( d, names::weight, weight_ ); - def< double >( d, names::dU, U_ ); - def< double >( d, names::u, u_ ); - def< double >( d, names::tau_rec, tau_rec_ ); - def< double >( d, names::tau_fac, tau_fac_ ); - def< int >( d, names::n, n_ ); - def< int >( d, names::a, a_ ); -} - - -template < typename targetidentifierT > -void -quantal_stp_synapse< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) -{ - ConnectionBase::set_status( d, cm ); - updateValue< double >( d, names::weight, weight_ ); - - updateValue< double >( d, names::dU, U_ ); - if ( U_ > 1.0 or U_ < 0.0 ) - { - throw BadProperty( "'U' must be in [0,1]." ); - } - - updateValue< double >( d, names::u, u_ ); - if ( u_ > 1.0 or u_ < 0.0 ) - { - throw BadProperty( "'u' must be in [0,1]." ); - } - - updateValue< double >( d, names::tau_rec, tau_rec_ ); - if ( tau_rec_ <= 0.0 ) - { - throw BadProperty( "'tau_rec' must be > 0." ); - } - - updateValue< double >( d, names::tau_fac, tau_fac_ ); - if ( tau_fac_ < 0.0 ) - { - throw BadProperty( "'tau_fac' must be >= 0." ); - } - - updateValue< long >( d, names::n, n_ ); - updateValue< long >( d, names::a, a_ ); -} - -} // of namespace nest - -#endif // #ifndef QUANTAL_STP_SYNAPSE_IMPL_H diff --git a/models/rate_connection_delayed.cpp b/models/rate_connection_delayed.cpp index 8e2c986a90..c6373b43f7 100644 --- a/models/rate_connection_delayed.cpp +++ b/models/rate_connection_delayed.cpp @@ -22,9 +22,6 @@ #include "rate_connection_delayed.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_rate_connection_delayed( const std::string& name ) { diff --git a/models/rate_connection_instantaneous.cpp b/models/rate_connection_instantaneous.cpp index 89c88c5bd5..d45bad767c 100644 --- a/models/rate_connection_instantaneous.cpp +++ b/models/rate_connection_instantaneous.cpp @@ -22,9 +22,6 @@ #include "rate_connection_instantaneous.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_rate_connection_instantaneous( const std::string& name ) { diff --git a/models/rate_neuron_ipn.h b/models/rate_neuron_ipn.h index 14c22920ac..5140deb72a 100644 --- a/models/rate_neuron_ipn.h +++ b/models/rate_neuron_ipn.h @@ -27,19 +27,29 @@ #include "config.h" // C++ includes: +#include // in case we need isnan() // fabs #include // Includes from nestkernel: #include "archiving_node.h" #include "connection.h" #include "event.h" -#include "nest_types.h" +#include "exceptions.h" +#include "kernel_manager.h" #include "node.h" #include "random_generators.h" #include "recordables_map.h" #include "ring_buffer.h" #include "universal_data_logger.h" +// Includes from libnestutil: +#include "dict_util.h" +#include "numerics.h" + +// Includes from sli: +#include "dict.h" +#include "dictutils.h" + namespace nest { @@ -385,6 +395,429 @@ rate_neuron_ipn< TNonlinearities >::set_status( const DictionaryDatum& d ) nonlinearities_.set( d, this ); } +/* ---------------------------------------------------------------- + * Recordables map + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +RecordablesMap< rate_neuron_ipn< TNonlinearities > > rate_neuron_ipn< TNonlinearities >::recordablesMap_; + +/* ---------------------------------------------------------------- + * Default constructors defining default parameters and state + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::Parameters_::Parameters_() + : tau_( 10.0 ) // ms + , lambda_( 1.0 ) // ms + , sigma_( 1.0 ) + , mu_( 0.0 ) + , rectify_rate_( 0.0 ) + , linear_summation_( true ) + , rectify_output_( false ) + , mult_coupling_( false ) +{ + recordablesMap_.create(); +} + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::State_::State_() + : rate_( 0.0 ) + , noise_( 0.0 ) +{ +} + +/* ---------------------------------------------------------------- + * Parameter and state extractions and manipulation functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const +{ + def< double >( d, names::tau, tau_ ); + def< double >( d, names::lambda, lambda_ ); + def< double >( d, names::sigma, sigma_ ); + def< double >( d, names::mu, mu_ ); + def< double >( d, names::rectify_rate, rectify_rate_ ); + def< bool >( d, names::linear_summation, linear_summation_ ); + def< bool >( d, names::rectify_output, rectify_output_ ); + def< bool >( d, names::mult_coupling, mult_coupling_ ); + + // Also allow old names (to not break old scripts) + def< double >( d, names::std, sigma_ ); + def< double >( d, names::mean, mu_ ); +} + +template < class TNonlinearities > +void +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 ); + updateValueParam< double >( d, names::mu, mu_, node ); + updateValueParam< double >( d, names::rectify_rate, rectify_rate_, node ); + updateValueParam< double >( d, names::sigma, sigma_, node ); + updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); + updateValueParam< bool >( d, names::rectify_output, rectify_output_, node ); + updateValueParam< bool >( d, names::mult_coupling, mult_coupling_, node ); + + // Check for old names + if ( updateValueParam< double >( d, names::mean, mu_, node ) ) + { + LOG( M_WARNING, + "rate_neuron_ipn< TNonlinearities >::Parameters_::set", + "The parameter mean has been renamed to mu. Please use the new " + "name from now on." ); + } + + if ( updateValueParam< double >( d, names::std, sigma_, node ) ) + { + LOG( M_WARNING, + "rate_neuron_ipn< TNonlinearities >::Parameters_::set", + "The parameter std has been renamed to sigma. Please use the new " + "name from now on." ); + } + + // Check for invalid parameters + if ( tau_ <= 0 ) + { + throw BadProperty( "Time constant must be > 0." ); + } + if ( lambda_ < 0 ) + { + throw BadProperty( "Passive decay rate must be >= 0." ); + } + if ( sigma_ < 0 ) + { + throw BadProperty( "Noise parameter must not be negative." ); + } + if ( rectify_rate_ < 0 ) + { + throw BadProperty( "Rectifying rate must not be negative." ); + } +} + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::State_::get( DictionaryDatum& d ) const +{ + def< double >( d, names::rate, rate_ ); // Rate + def< double >( d, names::noise, noise_ ); // Noise +} + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) +{ + updateValueParam< double >( d, names::rate, rate_, node ); // Rate +} + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( rate_neuron_ipn< TNonlinearities >& n ) + : logger_( n ) +{ +} + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_ipn< TNonlinearities >& n ) + : logger_( n ) +{ +} + +/* ---------------------------------------------------------------- + * Default and copy constructor for node + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn() + : ArchivingNode() + , P_() + , S_() + , B_( *this ) +{ + recordablesMap_.create(); + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +template < class TNonlinearities > +rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn( const rate_neuron_ipn& n ) + : ArchivingNode( n ) + , nonlinearities_( n.nonlinearities_ ) + , P_( n.P_ ) + , S_( n.S_ ) + , B_( n.B_, *this ) +{ + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +/* ---------------------------------------------------------------- + * Node initialization functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::init_buffers_() +{ + B_.delayed_rates_ex_.clear(); // includes resize + B_.delayed_rates_in_.clear(); // includes resize + + // resize buffers + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + B_.instant_rates_ex_.resize( buffer_size, 0.0 ); + B_.instant_rates_in_.resize( buffer_size, 0.0 ); + B_.last_y_values.resize( buffer_size, 0.0 ); + B_.random_numbers.resize( buffer_size, numerics::nan ); + + // initialize random numbers + for ( unsigned int i = 0; i < buffer_size; i++ ) + { + B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); + } + + B_.logger_.reset(); // includes resize + ArchivingNode::clear_history(); +} + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::pre_run_hook() +{ + B_.logger_.init(); // ensures initialization in case mm connected after Simulate + + const double h = Time::get_resolution().get_ms(); + + if ( P_.lambda_ > 0 ) + { + // use stochastic exponential Euler method + V_.P1_ = std::exp( -P_.lambda_ * h / P_.tau_ ); + V_.P2_ = -1.0 / P_.lambda_ * numerics::expm1( -P_.lambda_ * h / P_.tau_ ); + V_.input_noise_factor_ = std::sqrt( -0.5 / P_.lambda_ * numerics::expm1( -2. * P_.lambda_ * h / P_.tau_ ) ); + } + else + { + // use Euler-Maruyama method + V_.P1_ = 1; + V_.P2_ = h / P_.tau_; + V_.input_noise_factor_ = std::sqrt( h / P_.tau_ ); + } +} + +/* ---------------------------------------------------------------- + * Update and event handling functions + */ + +template < class TNonlinearities > +bool +rate_neuron_ipn< TNonlinearities >::update_( Time const& origin, + const long from, + const long to, + const bool called_from_wfr_update ) +{ + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); + bool wfr_tol_exceeded = false; + + // allocate memory to store rates to be sent by rate events + std::vector< double > new_rates( buffer_size, 0.0 ); + + for ( long lag = from; lag < to; ++lag ) + { + // store rate + new_rates[ lag ] = S_.rate_; + // get noise + S_.noise_ = P_.sigma_ * B_.random_numbers[ lag ]; + // propagate rate to new time step (exponential integration) + S_.rate_ = V_.P1_ * new_rates[ lag ] + V_.P2_ * P_.mu_ + V_.input_noise_factor_ * S_.noise_; + + double delayed_rates_in = 0; + double delayed_rates_ex = 0; + if ( called_from_wfr_update ) + { + // use get_value_wfr_update to keep values in buffer + delayed_rates_in = B_.delayed_rates_in_.get_value_wfr_update( lag ); + delayed_rates_ex = B_.delayed_rates_ex_.get_value_wfr_update( lag ); + } + else + { + // use get_value to clear values in buffer after reading + delayed_rates_in = B_.delayed_rates_in_.get_value( lag ); + delayed_rates_ex = B_.delayed_rates_ex_.get_value( lag ); + } + double instant_rates_in = B_.instant_rates_in_[ lag ]; + double instant_rates_ex = B_.instant_rates_ex_[ lag ]; + double H_ex = 1.; // valid value for non-multiplicative coupling + double H_in = 1.; // valid value for non-multiplicative coupling + if ( P_.mult_coupling_ ) + { + H_ex = nonlinearities_.mult_coupling_ex( new_rates[ lag ] ); + H_in = nonlinearities_.mult_coupling_in( new_rates[ lag ] ); + } + + if ( P_.linear_summation_ ) + { + // In this case we explicitly need to distinguish the cases of + // multiplicative coupling and non-multiplicative coupling in + // order to compute input( ex + in ) instead of input(ex) + input(in) in + // the non-multiplicative case. + if ( P_.mult_coupling_ ) + { + S_.rate_ += V_.P2_ * H_ex * nonlinearities_.input( delayed_rates_ex + instant_rates_ex ); + S_.rate_ += V_.P2_ * H_in * nonlinearities_.input( delayed_rates_in + instant_rates_in ); + } + else + { + S_.rate_ += + V_.P2_ * nonlinearities_.input( delayed_rates_ex + instant_rates_ex + delayed_rates_in + instant_rates_in ); + } + } + else + { + // In this case multiplicative and non-multiplicative coupling + // can be handled with the same code. + S_.rate_ += V_.P2_ * H_ex * ( delayed_rates_ex + instant_rates_ex ); + S_.rate_ += V_.P2_ * H_in * ( delayed_rates_in + instant_rates_in ); + } + + if ( P_.rectify_output_ and S_.rate_ < P_.rectify_rate_ ) + { + S_.rate_ = P_.rectify_rate_; + } + + if ( called_from_wfr_update ) + { + // check if deviation from last iteration exceeds wfr_tol + wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; + // update last_y_values for next wfr iteration + B_.last_y_values[ lag ] = S_.rate_; + } + else + { + // rate logging + B_.logger_.record_data( origin.get_steps() + lag ); + } + } + + if ( not called_from_wfr_update ) + { + // Send delay-rate-neuron-event. This only happens in the final iteration + // to avoid accumulation in the buffers of the receiving neurons. + DelayedRateConnectionEvent drve; + drve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, drve ); + + // clear last_y_values + std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); + + // modifiy new_rates for rate-neuron-event as proxy for next min_delay + for ( long temp = from; temp < to; ++temp ) + { + new_rates[ temp ] = S_.rate_; + } + + // create new random numbers + B_.random_numbers.resize( buffer_size, numerics::nan ); + for ( unsigned int i = 0; i < buffer_size; i++ ) + { + B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); + } + } + + // Send rate-neuron-event + InstantaneousRateConnectionEvent rve; + rve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, rve ); + + // Reset variables + std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ex_ ); + std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_in_ ); + + return wfr_tol_exceeded; +} + + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) +{ + const double weight = e.get_weight(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + if ( weight >= 0.0 ) + { + B_.instant_rates_ex_[ i ] += weight * e.get_coeffvalue( it ); + } + else + { + B_.instant_rates_in_[ i ] += weight * e.get_coeffvalue( it ); + } + } + else + { + if ( weight >= 0.0 ) + { + B_.instant_rates_ex_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); + } + else + { + B_.instant_rates_in_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); + } + } + i++; + } +} + +template < class TNonlinearities > +void +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(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + if ( weight >= 0.0 ) + { + B_.delayed_rates_ex_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); + } + else + { + B_.delayed_rates_in_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); + } + } + else + { + if ( weight >= 0.0 ) + { + B_.delayed_rates_ex_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); + } + else + { + B_.delayed_rates_in_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); + } + } + ++i; + } +} + +template < class TNonlinearities > +void +rate_neuron_ipn< TNonlinearities >::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); +} + } // namespace #endif /* #ifndef RATE_NEURON_IPN_H */ diff --git a/models/rate_neuron_ipn_impl.h b/models/rate_neuron_ipn_impl.h deleted file mode 100644 index 286c22c0af..0000000000 --- a/models/rate_neuron_ipn_impl.h +++ /dev/null @@ -1,479 +0,0 @@ -/* - * rate_neuron_ipn_impl.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 RATE_NEURON_IPN_IMPL_H -#define RATE_NEURON_IPN_IMPL_H - -#include "rate_neuron_ipn.h" - -// C++ includes: -#include // in case we need isnan() // fabs -#include -#include -#include -#include -#include - -// Includes from libnestutil: -#include "dict_util.h" -#include "numerics.h" - -// Includes from nestkernel: -#include "exceptions.h" -#include "kernel_manager.h" -#include "universal_data_logger_impl.h" - -// Includes from sli: -#include "dict.h" -#include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" - -namespace nest -{ - -/* ---------------------------------------------------------------- - * Recordables map - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -RecordablesMap< rate_neuron_ipn< TNonlinearities > > rate_neuron_ipn< TNonlinearities >::recordablesMap_; - -/* ---------------------------------------------------------------- - * Default constructors defining default parameters and state - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::Parameters_::Parameters_() - : tau_( 10.0 ) // ms - , lambda_( 1.0 ) // ms - , sigma_( 1.0 ) - , mu_( 0.0 ) - , rectify_rate_( 0.0 ) - , linear_summation_( true ) - , rectify_output_( false ) - , mult_coupling_( false ) -{ - recordablesMap_.create(); -} - -template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::State_::State_() - : rate_( 0.0 ) - , noise_( 0.0 ) -{ -} - -/* ---------------------------------------------------------------- - * Parameter and state extractions and manipulation functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const -{ - def< double >( d, names::tau, tau_ ); - def< double >( d, names::lambda, lambda_ ); - def< double >( d, names::sigma, sigma_ ); - def< double >( d, names::mu, mu_ ); - def< double >( d, names::rectify_rate, rectify_rate_ ); - def< bool >( d, names::linear_summation, linear_summation_ ); - def< bool >( d, names::rectify_output, rectify_output_ ); - def< bool >( d, names::mult_coupling, mult_coupling_ ); - - // Also allow old names (to not break old scripts) - def< double >( d, names::std, sigma_ ); - def< double >( d, names::mean, mu_ ); -} - -template < class TNonlinearities > -void -nest::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 ); - updateValueParam< double >( d, names::mu, mu_, node ); - updateValueParam< double >( d, names::rectify_rate, rectify_rate_, node ); - updateValueParam< double >( d, names::sigma, sigma_, node ); - updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); - updateValueParam< bool >( d, names::rectify_output, rectify_output_, node ); - updateValueParam< bool >( d, names::mult_coupling, mult_coupling_, node ); - - // Check for old names - if ( updateValueParam< double >( d, names::mean, mu_, node ) ) - { - LOG( M_WARNING, - "rate_neuron_ipn< TNonlinearities >::Parameters_::set", - "The parameter mean has been renamed to mu. Please use the new " - "name from now on." ); - } - - if ( updateValueParam< double >( d, names::std, sigma_, node ) ) - { - LOG( M_WARNING, - "rate_neuron_ipn< TNonlinearities >::Parameters_::set", - "The parameter std has been renamed to sigma. Please use the new " - "name from now on." ); - } - - // Check for invalid parameters - if ( tau_ <= 0 ) - { - throw BadProperty( "Time constant must be > 0." ); - } - if ( lambda_ < 0 ) - { - throw BadProperty( "Passive decay rate must be >= 0." ); - } - if ( sigma_ < 0 ) - { - throw BadProperty( "Noise parameter must not be negative." ); - } - if ( rectify_rate_ < 0 ) - { - throw BadProperty( "Rectifying rate must not be negative." ); - } -} - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::State_::get( DictionaryDatum& d ) const -{ - def< double >( d, names::rate, rate_ ); // Rate - def< double >( d, names::noise, noise_ ); // Noise -} - -template < class TNonlinearities > -void -nest::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 ) - : logger_( n ) -{ -} - -template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_ipn< TNonlinearities >& n ) - : logger_( n ) -{ -} - -/* ---------------------------------------------------------------- - * Default and copy constructor for node - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn() - : ArchivingNode() - , P_() - , S_() - , B_( *this ) -{ - recordablesMap_.create(); - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -template < class TNonlinearities > -nest::rate_neuron_ipn< TNonlinearities >::rate_neuron_ipn( const rate_neuron_ipn& n ) - : ArchivingNode( n ) - , nonlinearities_( n.nonlinearities_ ) - , P_( n.P_ ) - , S_( n.S_ ) - , B_( n.B_, *this ) -{ - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -/* ---------------------------------------------------------------- - * Node initialization functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::init_buffers_() -{ - B_.delayed_rates_ex_.clear(); // includes resize - B_.delayed_rates_in_.clear(); // includes resize - - // resize buffers - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - B_.instant_rates_ex_.resize( buffer_size, 0.0 ); - B_.instant_rates_in_.resize( buffer_size, 0.0 ); - B_.last_y_values.resize( buffer_size, 0.0 ); - B_.random_numbers.resize( buffer_size, numerics::nan ); - - // initialize random numbers - for ( unsigned int i = 0; i < buffer_size; i++ ) - { - B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); - } - - B_.logger_.reset(); // includes resize - ArchivingNode::clear_history(); -} - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::pre_run_hook() -{ - B_.logger_.init(); // ensures initialization in case mm connected after Simulate - - const double h = Time::get_resolution().get_ms(); - - if ( P_.lambda_ > 0 ) - { - // use stochastic exponential Euler method - V_.P1_ = std::exp( -P_.lambda_ * h / P_.tau_ ); - V_.P2_ = -1.0 / P_.lambda_ * numerics::expm1( -P_.lambda_ * h / P_.tau_ ); - V_.input_noise_factor_ = std::sqrt( -0.5 / P_.lambda_ * numerics::expm1( -2. * P_.lambda_ * h / P_.tau_ ) ); - } - else - { - // use Euler-Maruyama method - V_.P1_ = 1; - V_.P2_ = h / P_.tau_; - V_.input_noise_factor_ = std::sqrt( h / P_.tau_ ); - } -} - -/* ---------------------------------------------------------------- - * Update and event handling functions - */ - -template < class TNonlinearities > -bool -nest::rate_neuron_ipn< TNonlinearities >::update_( Time const& origin, - const long from, - const long to, - const bool called_from_wfr_update ) -{ - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); - bool wfr_tol_exceeded = false; - - // allocate memory to store rates to be sent by rate events - std::vector< double > new_rates( buffer_size, 0.0 ); - - for ( long lag = from; lag < to; ++lag ) - { - // store rate - new_rates[ lag ] = S_.rate_; - // get noise - S_.noise_ = P_.sigma_ * B_.random_numbers[ lag ]; - // propagate rate to new time step (exponential integration) - S_.rate_ = V_.P1_ * new_rates[ lag ] + V_.P2_ * P_.mu_ + V_.input_noise_factor_ * S_.noise_; - - double delayed_rates_in = 0; - double delayed_rates_ex = 0; - if ( called_from_wfr_update ) - { - // use get_value_wfr_update to keep values in buffer - delayed_rates_in = B_.delayed_rates_in_.get_value_wfr_update( lag ); - delayed_rates_ex = B_.delayed_rates_ex_.get_value_wfr_update( lag ); - } - else - { - // use get_value to clear values in buffer after reading - delayed_rates_in = B_.delayed_rates_in_.get_value( lag ); - delayed_rates_ex = B_.delayed_rates_ex_.get_value( lag ); - } - double instant_rates_in = B_.instant_rates_in_[ lag ]; - double instant_rates_ex = B_.instant_rates_ex_[ lag ]; - double H_ex = 1.; // valid value for non-multiplicative coupling - double H_in = 1.; // valid value for non-multiplicative coupling - if ( P_.mult_coupling_ ) - { - H_ex = nonlinearities_.mult_coupling_ex( new_rates[ lag ] ); - H_in = nonlinearities_.mult_coupling_in( new_rates[ lag ] ); - } - - if ( P_.linear_summation_ ) - { - // In this case we explicitly need to distinguish the cases of - // multiplicative coupling and non-multiplicative coupling in - // order to compute input( ex + in ) instead of input(ex) + input(in) in - // the non-multiplicative case. - if ( P_.mult_coupling_ ) - { - S_.rate_ += V_.P2_ * H_ex * nonlinearities_.input( delayed_rates_ex + instant_rates_ex ); - S_.rate_ += V_.P2_ * H_in * nonlinearities_.input( delayed_rates_in + instant_rates_in ); - } - else - { - S_.rate_ += - V_.P2_ * nonlinearities_.input( delayed_rates_ex + instant_rates_ex + delayed_rates_in + instant_rates_in ); - } - } - else - { - // In this case multiplicative and non-multiplicative coupling - // can be handled with the same code. - S_.rate_ += V_.P2_ * H_ex * ( delayed_rates_ex + instant_rates_ex ); - S_.rate_ += V_.P2_ * H_in * ( delayed_rates_in + instant_rates_in ); - } - - if ( P_.rectify_output_ and S_.rate_ < P_.rectify_rate_ ) - { - S_.rate_ = P_.rectify_rate_; - } - - if ( called_from_wfr_update ) - { - // check if deviation from last iteration exceeds wfr_tol - wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; - // update last_y_values for next wfr iteration - B_.last_y_values[ lag ] = S_.rate_; - } - else - { - // rate logging - B_.logger_.record_data( origin.get_steps() + lag ); - } - } - - if ( not called_from_wfr_update ) - { - // Send delay-rate-neuron-event. This only happens in the final iteration - // to avoid accumulation in the buffers of the receiving neurons. - DelayedRateConnectionEvent drve; - drve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, drve ); - - // clear last_y_values - std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); - - // modifiy new_rates for rate-neuron-event as proxy for next min_delay - for ( long temp = from; temp < to; ++temp ) - { - new_rates[ temp ] = S_.rate_; - } - - // create new random numbers - B_.random_numbers.resize( buffer_size, numerics::nan ); - for ( unsigned int i = 0; i < buffer_size; i++ ) - { - B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); - } - } - - // Send rate-neuron-event - InstantaneousRateConnectionEvent rve; - rve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, rve ); - - // Reset variables - std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ex_ ); - std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_in_ ); - - return wfr_tol_exceeded; -} - - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) -{ - const double weight = e.get_weight(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - if ( weight >= 0.0 ) - { - B_.instant_rates_ex_[ i ] += weight * e.get_coeffvalue( it ); - } - else - { - B_.instant_rates_in_[ i ] += weight * e.get_coeffvalue( it ); - } - } - else - { - if ( weight >= 0.0 ) - { - B_.instant_rates_ex_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); - } - else - { - B_.instant_rates_in_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); - } - } - i++; - } -} - -template < class TNonlinearities > -void -nest::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(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - if ( weight >= 0.0 ) - { - B_.delayed_rates_ex_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); - } - else - { - B_.delayed_rates_in_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); - } - } - else - { - if ( weight >= 0.0 ) - { - B_.delayed_rates_ex_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); - } - else - { - B_.delayed_rates_in_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); - } - } - ++i; - } -} - -template < class TNonlinearities > -void -nest::rate_neuron_ipn< TNonlinearities >::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); -} - -} // namespace - -#endif /* #ifndef RATE_NEURON_IPN_IMPL_H */ diff --git a/models/rate_neuron_opn.h b/models/rate_neuron_opn.h index 1d4232c111..e08448ced6 100644 --- a/models/rate_neuron_opn.h +++ b/models/rate_neuron_opn.h @@ -23,17 +23,23 @@ #ifndef RATE_NEURON_OPN_H #define RATE_NEURON_OPN_H -// Generated includes: -#include "config.h" - // C++ includes: +#include // in case we need isnan() // fabs #include +// Includes from libnestutil: +#include "numerics.h" + +// Includes from sli: +#include "dict.h" +#include "dictutils.h" + // Includes from nestkernel: #include "archiving_node.h" #include "connection.h" #include "event.h" -#include "nest_types.h" +#include "exceptions.h" +#include "kernel_manager.h" #include "node.h" #include "random_generators.h" #include "recordables_map.h" @@ -383,6 +389,403 @@ rate_neuron_opn< TNonlinearities >::set_status( const DictionaryDatum& d ) nonlinearities_.set( d, this ); } +/* ---------------------------------------------------------------- + * Recordables map + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +RecordablesMap< rate_neuron_opn< TNonlinearities > > rate_neuron_opn< TNonlinearities >::recordablesMap_; + + +/* ---------------------------------------------------------------- + * Default constructors defining default parameters and state + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::Parameters_::Parameters_() + : tau_( 10.0 ) // ms + , sigma_( 1.0 ) + , mu_( 0.0 ) + , linear_summation_( true ) + , mult_coupling_( false ) +{ + recordablesMap_.create(); +} + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::State_::State_() + : rate_( 0.0 ) + , noise_( 0.0 ) + , noisy_rate_( 0.0 ) +{ +} + +/* ---------------------------------------------------------------- + * Parameter and state extractions and manipulation functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const +{ + def< double >( d, names::tau, tau_ ); + def< double >( d, names::sigma, sigma_ ); + def< double >( d, names::mu, mu_ ); + def< bool >( d, names::linear_summation, linear_summation_ ); + def< bool >( d, names::mult_coupling, mult_coupling_ ); + + // Also allow old names (to not break old scripts) + def< double >( d, names::std, sigma_ ); + def< double >( d, names::mean, mu_ ); +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) +{ + updateValueParam< double >( d, names::tau, tau_, node ); + updateValueParam< double >( d, names::mu, mu_, node ); + updateValueParam< double >( d, names::sigma, sigma_, node ); + updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); + updateValueParam< bool >( d, names::mult_coupling, mult_coupling_, node ); + + // Check for old names + if ( updateValueParam< double >( d, names::mean, mu_, node ) ) + { + LOG( M_WARNING, + "rate_neuron_opn< TNonlinearities >::Parameters_::set", + "The parameter mean has been renamed to mu. Please use the new " + "name from now on." ); + } + + if ( updateValueParam< double >( d, names::std, sigma_, node ) ) + { + LOG( M_WARNING, + "rate_neuron_opn< TNonlinearities >::Parameters_::set", + "The parameter std has been renamed to sigma. Please use the new " + "name from now on." ); + } + + // Check for invalid parameters + if ( tau_ <= 0 ) + { + throw BadProperty( "Time constant must be > 0." ); + } + if ( sigma_ < 0 ) + { + throw BadProperty( "Noise parameter must not be negative." ); + } +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::State_::get( DictionaryDatum& d ) const +{ + def< double >( d, names::rate, rate_ ); // Rate + def< double >( d, names::noise, noise_ ); // Noise + def< double >( d, names::noisy_rate, noisy_rate_ ); // Noisy rate +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) +{ + updateValueParam< double >( d, names::rate, rate_, node ); // Rate +} + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::Buffers_::Buffers_( rate_neuron_opn< TNonlinearities >& n ) + : logger_( n ) +{ +} + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_opn< TNonlinearities >& n ) + : logger_( n ) +{ +} + +/* ---------------------------------------------------------------- + * Default and copy constructor for node + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::rate_neuron_opn() + : ArchivingNode() + , P_() + , S_() + , B_( *this ) +{ + recordablesMap_.create(); + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +template < class TNonlinearities > +nest::rate_neuron_opn< TNonlinearities >::rate_neuron_opn( const rate_neuron_opn& n ) + : ArchivingNode( n ) + , P_( n.P_ ) + , S_( n.S_ ) + , B_( n.B_, *this ) +{ + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +/* ---------------------------------------------------------------- + * Node initialization functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::init_buffers_() +{ + B_.delayed_rates_ex_.clear(); // includes resize + B_.delayed_rates_in_.clear(); // includes resize + + // resize buffers + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + B_.instant_rates_ex_.resize( buffer_size, 0.0 ); + B_.instant_rates_in_.resize( buffer_size, 0.0 ); + B_.last_y_values.resize( buffer_size, 0.0 ); + B_.random_numbers.resize( buffer_size, numerics::nan ); + + // initialize random numbers + for ( unsigned int i = 0; i < buffer_size; i++ ) + { + B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); + } + + B_.logger_.reset(); // includes resize + ArchivingNode::clear_history(); +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::pre_run_hook() +{ + B_.logger_.init(); // ensures initialization in case mm connected after Simulate + + const double h = Time::get_resolution().get_ms(); + + // propagators + V_.P1_ = std::exp( -h / P_.tau_ ); + V_.P2_ = -numerics::expm1( -h / P_.tau_ ); + + // Gaussian white noise approximated by piecewise constant value + V_.output_noise_factor_ = std::sqrt( P_.tau_ / h ); +} + +/* ---------------------------------------------------------------- + * Update and event handling functions + */ + +template < class TNonlinearities > +bool +nest::rate_neuron_opn< TNonlinearities >::update_( Time const& origin, + const long from, + const long to, + const bool called_from_wfr_update ) +{ + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); + bool wfr_tol_exceeded = false; + + // allocate memory to store rates to be sent by rate events + std::vector< double > new_rates( buffer_size, 0.0 ); + + for ( long lag = from; lag < to; ++lag ) + { + // get noise + S_.noise_ = P_.sigma_ * B_.random_numbers[ lag ]; + // the noise is added to the noisy_rate variable + S_.noisy_rate_ = S_.rate_ + V_.output_noise_factor_ * S_.noise_; + // store rate + new_rates[ lag ] = S_.noisy_rate_; + // propagate rate to new time step (exponential integration) + S_.rate_ = V_.P1_ * S_.rate_ + V_.P2_ * P_.mu_; + + double delayed_rates_in = 0; + double delayed_rates_ex = 0; + if ( called_from_wfr_update ) + { + // use get_value_wfr_update to keep values in buffer + delayed_rates_in = B_.delayed_rates_in_.get_value_wfr_update( lag ); + delayed_rates_ex = B_.delayed_rates_ex_.get_value_wfr_update( lag ); + } + else + { + // use get_value to clear values in buffer after reading + delayed_rates_in = B_.delayed_rates_in_.get_value( lag ); + delayed_rates_ex = B_.delayed_rates_ex_.get_value( lag ); + } + double instant_rates_in = B_.instant_rates_in_[ lag ]; + double instant_rates_ex = B_.instant_rates_ex_[ lag ]; + double H_ex = 1.; // valid value for non-multiplicative coupling + double H_in = 1.; // valid value for non-multiplicative coupling + if ( P_.mult_coupling_ ) + { + H_ex = nonlinearities_.mult_coupling_ex( new_rates[ lag ] ); + H_in = nonlinearities_.mult_coupling_in( new_rates[ lag ] ); + } + + if ( P_.linear_summation_ ) + { + // In this case we explicitly need to distinguish the cases of + // multiplicative coupling and non-multiplicative coupling in + // order to compute input( ex + in ) instead of input(ex) + input(in) in + // the non-multiplicative case. + if ( P_.mult_coupling_ ) + { + S_.rate_ += V_.P2_ * H_ex * nonlinearities_.input( delayed_rates_ex + instant_rates_ex ); + S_.rate_ += V_.P2_ * H_in * nonlinearities_.input( delayed_rates_in + instant_rates_in ); + } + else + { + S_.rate_ += + V_.P2_ * nonlinearities_.input( delayed_rates_ex + instant_rates_ex + delayed_rates_in + instant_rates_in ); + } + } + else + { + // In this case multiplicative and non-multiplicative coupling + // can be handled with the same code. + S_.rate_ += V_.P2_ * H_ex * ( delayed_rates_ex + instant_rates_ex ); + S_.rate_ += V_.P2_ * H_in * ( delayed_rates_in + instant_rates_in ); + } + + if ( called_from_wfr_update ) + { + // check if deviation from last iteration exceeds wfr_tol + wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; + // update last_y_values for next wfr iteration + B_.last_y_values[ lag ] = S_.rate_; + } + else + { + // rate logging + B_.logger_.record_data( origin.get_steps() + lag ); + } + } + + if ( not called_from_wfr_update ) + { + // Send delay-rate-neuron-event. This only happens in the final iteration + // to avoid accumulation in the buffers of the receiving neurons. + DelayedRateConnectionEvent drve; + drve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, drve ); + + // clear last_y_values + std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); + + // modify new_rates for rate-neuron-event as proxy for next min_delay + for ( long temp = from; temp < to; ++temp ) + { + new_rates[ temp ] = S_.noisy_rate_; + } + + // create new random numbers + B_.random_numbers.resize( buffer_size, numerics::nan ); + for ( unsigned int i = 0; i < buffer_size; i++ ) + { + B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); + } + } + + // Send rate-neuron-event + InstantaneousRateConnectionEvent rve; + rve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, rve ); + + // Reset variables + std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ex_ ); + std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_in_ ); + + return wfr_tol_exceeded; +} + + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) +{ + const double weight = e.get_weight(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + if ( weight >= 0.0 ) + { + B_.instant_rates_ex_[ i ] += weight * e.get_coeffvalue( it ); + } + else + { + B_.instant_rates_in_[ i ] += weight * e.get_coeffvalue( it ); + } + } + else + { + if ( weight >= 0.0 ) + { + B_.instant_rates_ex_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); + } + else + { + B_.instant_rates_in_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); + } + } + i++; + } +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) +{ + const double weight = e.get_weight(); + const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + if ( weight >= 0.0 ) + { + B_.delayed_rates_ex_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); + } + else + { + B_.delayed_rates_in_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); + } + } + else + { + if ( weight >= 0.0 ) + { + B_.delayed_rates_ex_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); + } + else + { + B_.delayed_rates_in_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); + } + } + ++i; + } +} + +template < class TNonlinearities > +void +nest::rate_neuron_opn< TNonlinearities >::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); +} + } // namespace #endif /* #ifndef RATE_NEURON_OPN_H */ diff --git a/models/rate_neuron_opn_impl.h b/models/rate_neuron_opn_impl.h deleted file mode 100644 index 2479fe8c23..0000000000 --- a/models/rate_neuron_opn_impl.h +++ /dev/null @@ -1,452 +0,0 @@ -/* - * rate_neuron_opn_impl.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 RATE_NEURON_OPN_IMPL_H -#define RATE_NEURON_OPN_IMPL_H - -#include "rate_neuron_opn.h" - -// C++ includes: -#include // in case we need isnan() // fabs -#include -#include -#include -#include -#include - -// Includes from libnestutil: -#include "numerics.h" - -// Includes from nestkernel: -#include "exceptions.h" -#include "kernel_manager.h" -#include "universal_data_logger_impl.h" - -// Includes from sli: -#include "dict.h" -#include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" - -namespace nest -{ - -/* ---------------------------------------------------------------- - * Recordables map - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -RecordablesMap< rate_neuron_opn< TNonlinearities > > rate_neuron_opn< TNonlinearities >::recordablesMap_; - - -/* ---------------------------------------------------------------- - * Default constructors defining default parameters and state - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::Parameters_::Parameters_() - : tau_( 10.0 ) // ms - , sigma_( 1.0 ) - , mu_( 0.0 ) - , linear_summation_( true ) - , mult_coupling_( false ) -{ - recordablesMap_.create(); -} - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::State_::State_() - : rate_( 0.0 ) - , noise_( 0.0 ) - , noisy_rate_( 0.0 ) -{ -} - -/* ---------------------------------------------------------------- - * Parameter and state extractions and manipulation functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const -{ - def< double >( d, names::tau, tau_ ); - def< double >( d, names::sigma, sigma_ ); - def< double >( d, names::mu, mu_ ); - def< bool >( d, names::linear_summation, linear_summation_ ); - def< bool >( d, names::mult_coupling, mult_coupling_ ); - - // Also allow old names (to not break old scripts) - def< double >( d, names::std, sigma_ ); - def< double >( d, names::mean, mu_ ); -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) -{ - updateValueParam< double >( d, names::tau, tau_, node ); - updateValueParam< double >( d, names::mu, mu_, node ); - updateValueParam< double >( d, names::sigma, sigma_, node ); - updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); - updateValueParam< bool >( d, names::mult_coupling, mult_coupling_, node ); - - // Check for old names - if ( updateValueParam< double >( d, names::mean, mu_, node ) ) - { - LOG( M_WARNING, - "rate_neuron_opn< TNonlinearities >::Parameters_::set", - "The parameter mean has been renamed to mu. Please use the new " - "name from now on." ); - } - - if ( updateValueParam< double >( d, names::std, sigma_, node ) ) - { - LOG( M_WARNING, - "rate_neuron_opn< TNonlinearities >::Parameters_::set", - "The parameter std has been renamed to sigma. Please use the new " - "name from now on." ); - } - - // Check for invalid parameters - if ( tau_ <= 0 ) - { - throw BadProperty( "Time constant must be > 0." ); - } - if ( sigma_ < 0 ) - { - throw BadProperty( "Noise parameter must not be negative." ); - } -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::State_::get( DictionaryDatum& d ) const -{ - def< double >( d, names::rate, rate_ ); // Rate - def< double >( d, names::noise, noise_ ); // Noise - def< double >( d, names::noisy_rate, noisy_rate_ ); // Noisy rate -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) -{ - updateValueParam< double >( d, names::rate, rate_, node ); // Rate -} - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::Buffers_::Buffers_( rate_neuron_opn< TNonlinearities >& n ) - : logger_( n ) -{ -} - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, rate_neuron_opn< TNonlinearities >& n ) - : logger_( n ) -{ -} - -/* ---------------------------------------------------------------- - * Default and copy constructor for node - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::rate_neuron_opn() - : ArchivingNode() - , P_() - , S_() - , B_( *this ) -{ - recordablesMap_.create(); - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -template < class TNonlinearities > -nest::rate_neuron_opn< TNonlinearities >::rate_neuron_opn( const rate_neuron_opn& n ) - : ArchivingNode( n ) - , P_( n.P_ ) - , S_( n.S_ ) - , B_( n.B_, *this ) -{ - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -/* ---------------------------------------------------------------- - * Node initialization functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::init_buffers_() -{ - B_.delayed_rates_ex_.clear(); // includes resize - B_.delayed_rates_in_.clear(); // includes resize - - // resize buffers - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - B_.instant_rates_ex_.resize( buffer_size, 0.0 ); - B_.instant_rates_in_.resize( buffer_size, 0.0 ); - B_.last_y_values.resize( buffer_size, 0.0 ); - B_.random_numbers.resize( buffer_size, numerics::nan ); - - // initialize random numbers - for ( unsigned int i = 0; i < buffer_size; i++ ) - { - B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); - } - - B_.logger_.reset(); // includes resize - ArchivingNode::clear_history(); -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::pre_run_hook() -{ - B_.logger_.init(); // ensures initialization in case mm connected after Simulate - - const double h = Time::get_resolution().get_ms(); - - // propagators - V_.P1_ = std::exp( -h / P_.tau_ ); - V_.P2_ = -numerics::expm1( -h / P_.tau_ ); - - // Gaussian white noise approximated by piecewise constant value - V_.output_noise_factor_ = std::sqrt( P_.tau_ / h ); -} - -/* ---------------------------------------------------------------- - * Update and event handling functions - */ - -template < class TNonlinearities > -bool -nest::rate_neuron_opn< TNonlinearities >::update_( Time const& origin, - const long from, - const long to, - const bool called_from_wfr_update ) -{ - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); - bool wfr_tol_exceeded = false; - - // allocate memory to store rates to be sent by rate events - std::vector< double > new_rates( buffer_size, 0.0 ); - - for ( long lag = from; lag < to; ++lag ) - { - // get noise - S_.noise_ = P_.sigma_ * B_.random_numbers[ lag ]; - // the noise is added to the noisy_rate variable - S_.noisy_rate_ = S_.rate_ + V_.output_noise_factor_ * S_.noise_; - // store rate - new_rates[ lag ] = S_.noisy_rate_; - // propagate rate to new time step (exponential integration) - S_.rate_ = V_.P1_ * S_.rate_ + V_.P2_ * P_.mu_; - - double delayed_rates_in = 0; - double delayed_rates_ex = 0; - if ( called_from_wfr_update ) - { - // use get_value_wfr_update to keep values in buffer - delayed_rates_in = B_.delayed_rates_in_.get_value_wfr_update( lag ); - delayed_rates_ex = B_.delayed_rates_ex_.get_value_wfr_update( lag ); - } - else - { - // use get_value to clear values in buffer after reading - delayed_rates_in = B_.delayed_rates_in_.get_value( lag ); - delayed_rates_ex = B_.delayed_rates_ex_.get_value( lag ); - } - double instant_rates_in = B_.instant_rates_in_[ lag ]; - double instant_rates_ex = B_.instant_rates_ex_[ lag ]; - double H_ex = 1.; // valid value for non-multiplicative coupling - double H_in = 1.; // valid value for non-multiplicative coupling - if ( P_.mult_coupling_ ) - { - H_ex = nonlinearities_.mult_coupling_ex( new_rates[ lag ] ); - H_in = nonlinearities_.mult_coupling_in( new_rates[ lag ] ); - } - - if ( P_.linear_summation_ ) - { - // In this case we explicitly need to distinguish the cases of - // multiplicative coupling and non-multiplicative coupling in - // order to compute input( ex + in ) instead of input(ex) + input(in) in - // the non-multiplicative case. - if ( P_.mult_coupling_ ) - { - S_.rate_ += V_.P2_ * H_ex * nonlinearities_.input( delayed_rates_ex + instant_rates_ex ); - S_.rate_ += V_.P2_ * H_in * nonlinearities_.input( delayed_rates_in + instant_rates_in ); - } - else - { - S_.rate_ += - V_.P2_ * nonlinearities_.input( delayed_rates_ex + instant_rates_ex + delayed_rates_in + instant_rates_in ); - } - } - else - { - // In this case multiplicative and non-multiplicative coupling - // can be handled with the same code. - S_.rate_ += V_.P2_ * H_ex * ( delayed_rates_ex + instant_rates_ex ); - S_.rate_ += V_.P2_ * H_in * ( delayed_rates_in + instant_rates_in ); - } - - if ( called_from_wfr_update ) - { - // check if deviation from last iteration exceeds wfr_tol - wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; - // update last_y_values for next wfr iteration - B_.last_y_values[ lag ] = S_.rate_; - } - else - { - // rate logging - B_.logger_.record_data( origin.get_steps() + lag ); - } - } - - if ( not called_from_wfr_update ) - { - // Send delay-rate-neuron-event. This only happens in the final iteration - // to avoid accumulation in the buffers of the receiving neurons. - DelayedRateConnectionEvent drve; - drve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, drve ); - - // clear last_y_values - std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); - - // modify new_rates for rate-neuron-event as proxy for next min_delay - for ( long temp = from; temp < to; ++temp ) - { - new_rates[ temp ] = S_.noisy_rate_; - } - - // create new random numbers - B_.random_numbers.resize( buffer_size, numerics::nan ); - for ( unsigned int i = 0; i < buffer_size; i++ ) - { - B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) ); - } - } - - // Send rate-neuron-event - InstantaneousRateConnectionEvent rve; - rve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, rve ); - - // Reset variables - std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ex_ ); - std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_in_ ); - - return wfr_tol_exceeded; -} - - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) -{ - const double weight = e.get_weight(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - if ( weight >= 0.0 ) - { - B_.instant_rates_ex_[ i ] += weight * e.get_coeffvalue( it ); - } - else - { - B_.instant_rates_in_[ i ] += weight * e.get_coeffvalue( it ); - } - } - else - { - if ( weight >= 0.0 ) - { - B_.instant_rates_ex_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); - } - else - { - B_.instant_rates_in_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); - } - } - i++; - } -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) -{ - const double weight = e.get_weight(); - const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - if ( weight >= 0.0 ) - { - B_.delayed_rates_ex_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); - } - else - { - B_.delayed_rates_in_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); - } - } - else - { - if ( weight >= 0.0 ) - { - B_.delayed_rates_ex_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); - } - else - { - B_.delayed_rates_in_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); - } - } - ++i; - } -} - -template < class TNonlinearities > -void -nest::rate_neuron_opn< TNonlinearities >::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); -} - -} // namespace - -#endif /* #ifndef RATE_NEURON_OPN_IMPL_H */ diff --git a/models/rate_transformer_node.h b/models/rate_transformer_node.h index 50383f18f7..7f3390c9a9 100644 --- a/models/rate_transformer_node.h +++ b/models/rate_transformer_node.h @@ -327,6 +327,268 @@ rate_transformer_node< TNonlinearities >::set_status( const DictionaryDatum& d ) nonlinearities_.set( d, this ); } +/* ---------------------------------------------------------------- + * Recordables map + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +RecordablesMap< rate_transformer_node< TNonlinearities > > rate_transformer_node< TNonlinearities >::recordablesMap_; + +/* ---------------------------------------------------------------- + * Default constructors defining default parameters and state + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::Parameters_::Parameters_() + : linear_summation_( true ) +{ +} + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::State_::State_() + : rate_( 0.0 ) +{ +} + +/* ---------------------------------------------------------------- + * Parameter and state extractions and manipulation functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const +{ + def< bool >( d, names::linear_summation, linear_summation_ ); +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) +{ + updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::State_::get( DictionaryDatum& d ) const +{ + def< double >( d, names::rate, rate_ ); // Rate +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) +{ + updateValueParam< double >( d, names::rate, rate_, node ); // Rate +} + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::Buffers_::Buffers_( rate_transformer_node< TNonlinearities >& n ) + : logger_( n ) +{ +} + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, + rate_transformer_node< TNonlinearities >& n ) + : logger_( n ) +{ +} + +/* ---------------------------------------------------------------- + * Default and copy constructor for node + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::rate_transformer_node() + : ArchivingNode() + , S_() + , B_( *this ) +{ + recordablesMap_.create(); + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +template < class TNonlinearities > +nest::rate_transformer_node< TNonlinearities >::rate_transformer_node( const rate_transformer_node& n ) + : ArchivingNode( n ) + , nonlinearities_( n.nonlinearities_ ) + , S_( n.S_ ) + , B_( n.B_, *this ) +{ + Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); +} + +/* ---------------------------------------------------------------- + * Node initialization functions + * ---------------------------------------------------------------- */ + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::init_buffers_() +{ + B_.delayed_rates_.clear(); // includes resize + + // resize buffers + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + B_.instant_rates_.resize( buffer_size, 0.0 ); + B_.last_y_values.resize( buffer_size, 0.0 ); + + B_.logger_.reset(); // includes resize + ArchivingNode::clear_history(); +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::pre_run_hook() +{ + B_.logger_.init(); // ensures initialization in case mm connected after Simulate +} + +/* ---------------------------------------------------------------- + * Update and event handling functions + */ + +template < class TNonlinearities > +bool +nest::rate_transformer_node< TNonlinearities >::update_( Time const& origin, + const long from, + const long to, + const bool called_from_wfr_update ) +{ + const size_t buffer_size = kernel().connection_manager.get_min_delay(); + const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); + bool wfr_tol_exceeded = false; + + // allocate memory to store rates to be sent by rate events + std::vector< double > new_rates( buffer_size, 0.0 ); + + for ( long lag = from; lag < to; ++lag ) + { + // store rate + new_rates[ lag ] = S_.rate_; + // reinitialize output rate + S_.rate_ = 0.0; + + double delayed_rates = 0; + if ( called_from_wfr_update ) + { + // use get_value_wfr_update to keep values in buffer + delayed_rates = B_.delayed_rates_.get_value_wfr_update( lag ); + } + else + { + // use get_value to clear values in buffer after reading + delayed_rates = B_.delayed_rates_.get_value( lag ); + } + + if ( P_.linear_summation_ ) + { + S_.rate_ += nonlinearities_.input( delayed_rates + B_.instant_rates_[ lag ] ); + } + else + { + S_.rate_ += delayed_rates + B_.instant_rates_[ lag ]; + } + + if ( called_from_wfr_update ) + { + // check if deviation from last iteration exceeds wfr_tol + wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; + // update last_y_values for next wfr iteration + B_.last_y_values[ lag ] = S_.rate_; + } + else + { + // rate logging + B_.logger_.record_data( origin.get_steps() + lag ); + } + } + + if ( not called_from_wfr_update ) + { + // Send delay-rate-neuron-event. This only happens in the final iteration + // to avoid accumulation in the buffers of the receiving neurons. + DelayedRateConnectionEvent drve; + drve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, drve ); + + // clear last_y_values + std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); + + // modifiy new_rates for rate-neuron-event as proxy for next min_delay + for ( long temp = from; temp < to; ++temp ) + { + new_rates[ temp ] = S_.rate_; + } + } + + // Send rate-neuron-event + InstantaneousRateConnectionEvent rve; + rve.set_coeffarray( new_rates ); + kernel().event_delivery_manager.send_secondary( *this, rve ); + + // Reset variables + std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ ); + + return wfr_tol_exceeded; +} + + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) +{ + const double weight = e.get_weight(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + B_.instant_rates_[ i ] += weight * e.get_coeffvalue( it ); + } + else + { + B_.instant_rates_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); + } + ++i; + } +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) +{ + const double weight = e.get_weight(); + const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay(); + + size_t i = 0; + std::vector< unsigned int >::iterator it = e.begin(); + // The call to get_coeffvalue( it ) in this loop also advances the iterator it + while ( it != e.end() ) + { + if ( P_.linear_summation_ ) + { + B_.delayed_rates_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); + } + else + { + B_.delayed_rates_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); + } + ++i; + } +} + +template < class TNonlinearities > +void +nest::rate_transformer_node< TNonlinearities >::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); +} + } // namespace #endif /* #ifndef RATE_TRANSFORMER_NODE_H */ diff --git a/models/rate_transformer_node_impl.h b/models/rate_transformer_node_impl.h deleted file mode 100644 index 2809b97130..0000000000 --- a/models/rate_transformer_node_impl.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * rate_transformer_node_impl.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 RATE_TRANSFORMER_NODE_IMPL_H -#define RATE_TRANSFORMER_NODE_IMPL_H - -#include "rate_transformer_node.h" - -// C++ includes: -#include // in case we need isnan() // fabs -#include -#include -#include -#include -#include - -// Includes from libnestutil: -#include "dict_util.h" -#include "numerics.h" - - -// Includes from nestkernel: -#include "exceptions.h" -#include "kernel_manager.h" -#include "universal_data_logger_impl.h" - -// Includes from sli: -#include "dict.h" -#include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" - -namespace nest -{ - -/* ---------------------------------------------------------------- - * Recordables map - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -RecordablesMap< rate_transformer_node< TNonlinearities > > rate_transformer_node< TNonlinearities >::recordablesMap_; - -/* ---------------------------------------------------------------- - * Default constructors defining default parameters and state - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::Parameters_::Parameters_() - : linear_summation_( true ) -{ -} - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::State_::State_() - : rate_( 0.0 ) -{ -} - -/* ---------------------------------------------------------------- - * Parameter and state extractions and manipulation functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::Parameters_::get( DictionaryDatum& d ) const -{ - def< bool >( d, names::linear_summation, linear_summation_ ); -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::Parameters_::set( const DictionaryDatum& d, Node* node ) -{ - updateValueParam< bool >( d, names::linear_summation, linear_summation_, node ); -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::State_::get( DictionaryDatum& d ) const -{ - def< double >( d, names::rate, rate_ ); // Rate -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::State_::set( const DictionaryDatum& d, Node* node ) -{ - updateValueParam< double >( d, names::rate, rate_, node ); // Rate -} - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::Buffers_::Buffers_( rate_transformer_node< TNonlinearities >& n ) - : logger_( n ) -{ -} - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::Buffers_::Buffers_( const Buffers_&, - rate_transformer_node< TNonlinearities >& n ) - : logger_( n ) -{ -} - -/* ---------------------------------------------------------------- - * Default and copy constructor for node - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::rate_transformer_node() - : ArchivingNode() - , S_() - , B_( *this ) -{ - recordablesMap_.create(); - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -template < class TNonlinearities > -nest::rate_transformer_node< TNonlinearities >::rate_transformer_node( const rate_transformer_node& n ) - : ArchivingNode( n ) - , nonlinearities_( n.nonlinearities_ ) - , S_( n.S_ ) - , B_( n.B_, *this ) -{ - Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() ); -} - -/* ---------------------------------------------------------------- - * Node initialization functions - * ---------------------------------------------------------------- */ - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::init_buffers_() -{ - B_.delayed_rates_.clear(); // includes resize - - // resize buffers - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - B_.instant_rates_.resize( buffer_size, 0.0 ); - B_.last_y_values.resize( buffer_size, 0.0 ); - - B_.logger_.reset(); // includes resize - ArchivingNode::clear_history(); -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::pre_run_hook() -{ - B_.logger_.init(); // ensures initialization in case mm connected after Simulate -} - -/* ---------------------------------------------------------------- - * Update and event handling functions - */ - -template < class TNonlinearities > -bool -nest::rate_transformer_node< TNonlinearities >::update_( Time const& origin, - const long from, - const long to, - const bool called_from_wfr_update ) -{ - const size_t buffer_size = kernel().connection_manager.get_min_delay(); - const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); - bool wfr_tol_exceeded = false; - - // allocate memory to store rates to be sent by rate events - std::vector< double > new_rates( buffer_size, 0.0 ); - - for ( long lag = from; lag < to; ++lag ) - { - // store rate - new_rates[ lag ] = S_.rate_; - // reinitialize output rate - S_.rate_ = 0.0; - - double delayed_rates = 0; - if ( called_from_wfr_update ) - { - // use get_value_wfr_update to keep values in buffer - delayed_rates = B_.delayed_rates_.get_value_wfr_update( lag ); - } - else - { - // use get_value to clear values in buffer after reading - delayed_rates = B_.delayed_rates_.get_value( lag ); - } - - if ( P_.linear_summation_ ) - { - S_.rate_ += nonlinearities_.input( delayed_rates + B_.instant_rates_[ lag ] ); - } - else - { - S_.rate_ += delayed_rates + B_.instant_rates_[ lag ]; - } - - if ( called_from_wfr_update ) - { - // check if deviation from last iteration exceeds wfr_tol - wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol; - // update last_y_values for next wfr iteration - B_.last_y_values[ lag ] = S_.rate_; - } - else - { - // rate logging - B_.logger_.record_data( origin.get_steps() + lag ); - } - } - - if ( not called_from_wfr_update ) - { - // Send delay-rate-neuron-event. This only happens in the final iteration - // to avoid accumulation in the buffers of the receiving neurons. - DelayedRateConnectionEvent drve; - drve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, drve ); - - // clear last_y_values - std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values ); - - // modifiy new_rates for rate-neuron-event as proxy for next min_delay - for ( long temp = from; temp < to; ++temp ) - { - new_rates[ temp ] = S_.rate_; - } - } - - // Send rate-neuron-event - InstantaneousRateConnectionEvent rve; - rve.set_coeffarray( new_rates ); - kernel().event_delivery_manager.send_secondary( *this, rve ); - - // Reset variables - std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ ); - - return wfr_tol_exceeded; -} - - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::handle( InstantaneousRateConnectionEvent& e ) -{ - const double weight = e.get_weight(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - B_.instant_rates_[ i ] += weight * e.get_coeffvalue( it ); - } - else - { - B_.instant_rates_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) ); - } - ++i; - } -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::handle( DelayedRateConnectionEvent& e ) -{ - const double weight = e.get_weight(); - const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay(); - - size_t i = 0; - std::vector< unsigned int >::iterator it = e.begin(); - // The call to get_coeffvalue( it ) in this loop also advances the iterator it - while ( it != e.end() ) - { - if ( P_.linear_summation_ ) - { - B_.delayed_rates_.add_value( delay + i, weight * e.get_coeffvalue( it ) ); - } - else - { - B_.delayed_rates_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) ); - } - ++i; - } -} - -template < class TNonlinearities > -void -nest::rate_transformer_node< TNonlinearities >::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); -} - -} // namespace - -#endif /* #ifndef RATE_TRANSFORMER_NODE_IMPL_H */ diff --git a/models/sic_connection.cpp b/models/sic_connection.cpp index d10b3b412b..25edb56841 100644 --- a/models/sic_connection.cpp +++ b/models/sic_connection.cpp @@ -22,9 +22,6 @@ #include "sic_connection.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_sic_connection( const std::string& name ) { diff --git a/models/siegert_neuron.cpp b/models/siegert_neuron.cpp index ec39ab5cec..1dd35eb371 100644 --- a/models/siegert_neuron.cpp +++ b/models/siegert_neuron.cpp @@ -26,7 +26,6 @@ // C++ includes: #include // in case we need isnan() // fabs -#include #include // Includes from libnestutil: @@ -36,11 +35,8 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: -#include "dict.h" #include "dictutils.h" struct my_params diff --git a/models/sigmoid_rate.cpp b/models/sigmoid_rate.cpp index b50e5b5867..c201130cb4 100644 --- a/models/sigmoid_rate.cpp +++ b/models/sigmoid_rate.cpp @@ -22,10 +22,7 @@ #include "sigmoid_rate.h" -// Includes from nestkernel -#include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include namespace nest { diff --git a/models/sigmoid_rate.h b/models/sigmoid_rate.h index 634ce53f9f..a675c77937 100644 --- a/models/sigmoid_rate.h +++ b/models/sigmoid_rate.h @@ -28,9 +28,7 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" namespace nest diff --git a/models/sigmoid_rate_gg_1998.cpp b/models/sigmoid_rate_gg_1998.cpp index 2fcea61a4a..d2772cd441 100644 --- a/models/sigmoid_rate_gg_1998.cpp +++ b/models/sigmoid_rate_gg_1998.cpp @@ -22,10 +22,7 @@ #include "sigmoid_rate_gg_1998.h" -// Includes from nestkernel -#include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include namespace nest { diff --git a/models/sigmoid_rate_gg_1998.h b/models/sigmoid_rate_gg_1998.h index 6039d9692b..b12c2c7df7 100644 --- a/models/sigmoid_rate_gg_1998.h +++ b/models/sigmoid_rate_gg_1998.h @@ -28,9 +28,7 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" namespace nest { diff --git a/models/sinusoidal_gamma_generator.cpp b/models/sinusoidal_gamma_generator.cpp index 30c49fe411..18c7321c32 100644 --- a/models/sinusoidal_gamma_generator.cpp +++ b/models/sinusoidal_gamma_generator.cpp @@ -35,11 +35,9 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "booldatum.h" diff --git a/models/sinusoidal_gamma_generator.h b/models/sinusoidal_gamma_generator.h index 2a570caa6b..f51956d5b0 100644 --- a/models/sinusoidal_gamma_generator.h +++ b/models/sinusoidal_gamma_generator.h @@ -33,7 +33,6 @@ // Includes from nestkernel: #include "connection.h" -#include "device_node.h" #include "event.h" #include "nest_types.h" #include "stimulation_device.h" diff --git a/models/sinusoidal_poisson_generator.cpp b/models/sinusoidal_poisson_generator.cpp index 6a24cfae5f..85248c4cb4 100644 --- a/models/sinusoidal_poisson_generator.cpp +++ b/models/sinusoidal_poisson_generator.cpp @@ -31,11 +31,9 @@ #include "numerics.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" +#include "event_delivery_manager.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "booldatum.h" diff --git a/models/spike_dilutor.cpp b/models/spike_dilutor.cpp index b4d105a70d..906aeba557 100644 --- a/models/spike_dilutor.cpp +++ b/models/spike_dilutor.cpp @@ -26,11 +26,8 @@ #include "dict_util.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" // Includes from sli: #include "dict.h" diff --git a/models/spike_generator.cpp b/models/spike_generator.cpp index c6153ede4c..40032bded7 100644 --- a/models/spike_generator.cpp +++ b/models/spike_generator.cpp @@ -23,13 +23,12 @@ #include "spike_generator.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from libnestutil: #include "dict_util.h" +#include "event_delivery_manager.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/spike_recorder.cpp b/models/spike_recorder.cpp index 5769fa60e7..760002abb7 100644 --- a/models/spike_recorder.cpp +++ b/models/spike_recorder.cpp @@ -27,10 +27,9 @@ #include "compose.hpp" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include "nest.h" +#include "node_manager.h" // Includes from sli: #include "dict.h" diff --git a/models/spike_train_injector.cpp b/models/spike_train_injector.cpp index 9d596a8e5a..fc9b320d6e 100644 --- a/models/spike_train_injector.cpp +++ b/models/spike_train_injector.cpp @@ -23,14 +23,12 @@ #include "spike_train_injector.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "exceptions.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" // Includes from libnestutil: #include "dict_util.h" +#include "event_delivery_manager.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/spin_detector.cpp b/models/spin_detector.cpp index 190ece15cb..d080eed688 100644 --- a/models/spin_detector.cpp +++ b/models/spin_detector.cpp @@ -22,19 +22,10 @@ #include "spin_detector.h" - -// Includes from libnestutil: -#include "compose.hpp" - // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include -// Includes from sli: -#include "dict.h" -#include "dictutils.h" void nest::register_spin_detector( const std::string& name ) diff --git a/models/static_synapse.cpp b/models/static_synapse.cpp index 5149f4032f..181adc02f5 100644 --- a/models/static_synapse.cpp +++ b/models/static_synapse.cpp @@ -22,9 +22,6 @@ #include "static_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_static_synapse( const std::string& name ) { diff --git a/models/static_synapse.h b/models/static_synapse.h index 25ebf2ce61..aa184fca73 100644 --- a/models/static_synapse.h +++ b/models/static_synapse.h @@ -25,6 +25,8 @@ // Includes from nestkernel: #include "connection.h" +#include "event_delivery_manager.h" +#include "target_identifier.h" namespace nest { diff --git a/models/static_synapse_hom_w.cpp b/models/static_synapse_hom_w.cpp index 5b5694fa67..e39614598b 100644 --- a/models/static_synapse_hom_w.cpp +++ b/models/static_synapse_hom_w.cpp @@ -22,9 +22,6 @@ #include "static_synapse_hom_w.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_static_synapse_hom_w( const std::string& name ) { diff --git a/models/stdp_dopamine_synapse.cpp b/models/stdp_dopamine_synapse.cpp index 1a7ba75eca..29cf8171f9 100644 --- a/models/stdp_dopamine_synapse.cpp +++ b/models/stdp_dopamine_synapse.cpp @@ -24,10 +24,7 @@ // Includes from nestkernel: #include "common_synapse_properties.h" -#include "connector_model.h" -#include "event.h" #include "kernel_manager.h" -#include "nest_impl.h" // Includes from sli: #include "dictdatum.h" diff --git a/models/stdp_facetshw_synapse_hom.cpp b/models/stdp_facetshw_synapse_hom.cpp index 09c328f4b1..2b9dcd03b1 100644 --- a/models/stdp_facetshw_synapse_hom.cpp +++ b/models/stdp_facetshw_synapse_hom.cpp @@ -21,10 +21,6 @@ */ #include "stdp_facetshw_synapse_hom.h" -#include "stdp_facetshw_synapse_hom_impl.h" - -// Includes from nestkernel: -#include "nest_impl.h" void nest::register_stdp_facetshw_synapse_hom( const std::string& name ) diff --git a/models/stdp_facetshw_synapse_hom.h b/models/stdp_facetshw_synapse_hom.h index 2b103eed48..10287f5188 100644 --- a/models/stdp_facetshw_synapse_hom.h +++ b/models/stdp_facetshw_synapse_hom.h @@ -536,6 +536,302 @@ stdp_facetshw_synapse_hom< targetidentifierT >::send( Event& e, return true; } + +template < typename targetidentifierT > +STDPFACETSHWHomCommonProperties< targetidentifierT >::STDPFACETSHWHomCommonProperties() + : CommonSynapseProperties() + , tau_plus_( 20.0 ) + , tau_minus_( 20.0 ) + , Wmax_( 100.0 ) + , no_synapses_( 0 ) + , synapses_per_driver_( 50 ) // hardware efficiency of 50/256=20%, + // which is comparable to Fieres et al. (2008) + , driver_readout_time_( 15.0 ) // in ms; measured on hardware +{ + lookuptable_0_.resize( 16 ); + lookuptable_1_.resize( 16 ); + lookuptable_2_.resize( 16 ); + + // intermediate Guetig (mu=0.4) + // with r=4 bits and n=36 SSPs, see [3]_ + lookuptable_0_.at( 0 ) = 2; + lookuptable_0_.at( 1 ) = 3; + lookuptable_0_.at( 2 ) = 4; + lookuptable_0_.at( 3 ) = 4; + lookuptable_0_.at( 4 ) = 5; + lookuptable_0_.at( 5 ) = 6; + lookuptable_0_.at( 6 ) = 7; + lookuptable_0_.at( 7 ) = 8; + lookuptable_0_.at( 8 ) = 9; + lookuptable_0_.at( 9 ) = 10; + lookuptable_0_.at( 10 ) = 11; + lookuptable_0_.at( 11 ) = 12; + lookuptable_0_.at( 12 ) = 13; + lookuptable_0_.at( 13 ) = 14; + lookuptable_0_.at( 14 ) = 14; + lookuptable_0_.at( 15 ) = 15; + + lookuptable_1_.at( 0 ) = 0; + lookuptable_1_.at( 1 ) = 0; + lookuptable_1_.at( 2 ) = 1; + lookuptable_1_.at( 3 ) = 2; + lookuptable_1_.at( 4 ) = 3; + lookuptable_1_.at( 5 ) = 4; + lookuptable_1_.at( 6 ) = 5; + lookuptable_1_.at( 7 ) = 6; + lookuptable_1_.at( 8 ) = 7; + lookuptable_1_.at( 9 ) = 8; + lookuptable_1_.at( 10 ) = 9; + lookuptable_1_.at( 11 ) = 10; + lookuptable_1_.at( 12 ) = 10; + lookuptable_1_.at( 13 ) = 11; + lookuptable_1_.at( 14 ) = 12; + lookuptable_1_.at( 15 ) = 13; + + for ( size_t i = 0; i < lookuptable_0_.size(); ++i ) + { + lookuptable_2_.at( i ) = i; + } + + configbit_0_.resize( 4 ); + configbit_1_.resize( 4 ); + + // see [4]_ + configbit_0_.at( 0 ) = 0; + configbit_0_.at( 1 ) = 0; + configbit_0_.at( 2 ) = 1; + configbit_0_.at( 3 ) = 0; + configbit_1_.at( 0 ) = 0; + configbit_1_.at( 1 ) = 1; + configbit_1_.at( 2 ) = 0; + configbit_1_.at( 3 ) = 0; + + reset_pattern_.resize( 6 ); + for ( size_t i = 0; i < reset_pattern_.size(); ++i ) + { + reset_pattern_.at( i ) = true; + } + + weight_per_lut_entry_ = Wmax_ / ( lookuptable_0_.size() - 1 ); + calc_readout_cycle_duration_(); +} + +template < typename targetidentifierT > +void +STDPFACETSHWHomCommonProperties< targetidentifierT >::calc_readout_cycle_duration_() +{ + readout_cycle_duration_ = int( ( no_synapses_ - 1.0 ) / synapses_per_driver_ + 1.0 ) * driver_readout_time_; +} + +template < typename targetidentifierT > +void +STDPFACETSHWHomCommonProperties< targetidentifierT >::get_status( DictionaryDatum& d ) const +{ + CommonSynapseProperties::get_status( d ); + + def< double >( d, names::tau_plus, tau_plus_ ); + def< double >( d, names::tau_minus_stdp, tau_minus_ ); + def< double >( d, names::Wmax, Wmax_ ); + def< double >( d, names::weight_per_lut_entry, weight_per_lut_entry_ ); + + def< long >( d, names::no_synapses, no_synapses_ ); + def< long >( d, names::synapses_per_driver, synapses_per_driver_ ); + def< double >( d, names::driver_readout_time, driver_readout_time_ ); + def< double >( d, names::readout_cycle_duration, readout_cycle_duration_ ); + + ( *d )[ names::lookuptable_0 ] = IntVectorDatum( new std::vector< long >( lookuptable_0_ ) ); + ( *d )[ names::lookuptable_1 ] = IntVectorDatum( new std::vector< long >( lookuptable_1_ ) ); + ( *d )[ names::lookuptable_2 ] = IntVectorDatum( new std::vector< long >( lookuptable_2_ ) ); + ( *d )[ names::configbit_0 ] = IntVectorDatum( new std::vector< long >( configbit_0_ ) ); + ( *d )[ names::configbit_1 ] = IntVectorDatum( new std::vector< long >( configbit_1_ ) ); + ( *d )[ names::reset_pattern ] = IntVectorDatum( new std::vector< long >( reset_pattern_ ) ); +} + +template < typename targetidentifierT > +void +STDPFACETSHWHomCommonProperties< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + CommonSynapseProperties::set_status( d, cm ); + + updateValue< double >( d, names::tau_plus, tau_plus_ ); + updateValue< double >( d, names::tau_minus_stdp, tau_minus_ ); + if ( updateValue< double >( d, names::Wmax, Wmax_ ) ) + { + weight_per_lut_entry_ = Wmax_ / ( lookuptable_0_.size() - 1 ); + } + + // TP: they should not be allowed to be changed! But needed for CopyModel ... + updateValue< double >( d, names::weight_per_lut_entry, weight_per_lut_entry_ ); + updateValue< double >( d, names::readout_cycle_duration, readout_cycle_duration_ ); + if ( updateValue< long >( d, names::no_synapses, no_synapses_ ) ) + { + calc_readout_cycle_duration_(); + } + + if ( updateValue< long >( d, names::synapses_per_driver, synapses_per_driver_ ) ) + { + calc_readout_cycle_duration_(); + } + if ( updateValue< double >( d, names::driver_readout_time, driver_readout_time_ ) ) + { + calc_readout_cycle_duration_(); + } + + if ( d->known( names::lookuptable_0 ) ) + { + updateValue< std::vector< long > >( d, names::lookuptable_0, lookuptable_0_ ); + + // right size? + if ( lookuptable_0_.size() != lookuptable_1_.size() ) + { + throw BadProperty( "Look-up table has not 2^4 entries!" ); + } + + // are look-up table entries out of bounds? + for ( size_t i = 0; i < size_t( lookuptable_0_.size() ); ++i ) + { + if ( lookuptable_0_[ i ] < 0 or lookuptable_0_[ i ] > 15 ) + { + throw BadProperty( "Look-up table entries must be integers in [0,15]" ); + } + } + } + if ( d->known( names::lookuptable_1 ) ) + { + updateValue< std::vector< long > >( d, names::lookuptable_1, lookuptable_1_ ); + + // right size? + if ( lookuptable_1_.size() != lookuptable_0_.size() ) + { + throw BadProperty( "Look-up table has not 2^4 entries!" ); + } + + // are look-up table entries out of bounds? + for ( size_t i = 0; i < size_t( lookuptable_1_.size() ); ++i ) + { + if ( lookuptable_1_[ i ] < 0 or lookuptable_1_[ i ] > 15 ) + { + throw BadProperty( "Look-up table entries must be integers in [0,15]" ); + } + } + } + if ( d->known( names::lookuptable_2 ) ) + { + updateValue< std::vector< long > >( d, names::lookuptable_2, lookuptable_2_ ); + + // right size? + if ( lookuptable_2_.size() != lookuptable_0_.size() ) + { + throw BadProperty( "Look-up table has not 2^4 entries!" ); + } + + // are look-up table entries out of bounds? + for ( size_t i = 0; i < size_t( lookuptable_2_.size() ); ++i ) + { + if ( lookuptable_2_[ i ] < 0 or lookuptable_2_[ i ] > 15 ) + { + throw BadProperty( "Look-up table entries must be integers in [0,15]" ); + } + } + } + + if ( d->known( names::configbit_0 ) ) + { + updateValue< std::vector< long > >( d, names::configbit_0, configbit_0_ ); + + // right size? + if ( configbit_0_.size() != 4 ) + { + throw BadProperty( "Wrong number of configuration bits (!=4)." ); + } + } + if ( d->known( names::configbit_1 ) ) + { + updateValue< std::vector< long > >( d, names::configbit_1, configbit_1_ ); + + // right size? + if ( configbit_1_.size() != 4 ) + { + throw BadProperty( "Wrong number of configuration bits (!=4)." ); + } + } + if ( d->known( names::reset_pattern ) ) + { + updateValue< std::vector< long > >( d, names::reset_pattern, reset_pattern_ ); + + // right size? + if ( reset_pattern_.size() != 6 ) + { + throw BadProperty( "Wrong number of reset bits (!=6)." ); + } + } +} + + +// +// Implementation of class stdp_facetshw_synapse_hom. +// +template < typename targetidentifierT > +stdp_facetshw_synapse_hom< targetidentifierT >::stdp_facetshw_synapse_hom() + : weight_( 1.0 ) + , a_causal_( 0.0 ) + , a_acausal_( 0.0 ) + , a_thresh_th_( 21.835 ) + , a_thresh_tl_( 21.835 ) // exp(-10ms/20ms) * 36SSPs + , init_flag_( false ) + , synapse_id_( 0 ) + , next_readout_time_( 0.0 ) + , discrete_weight_( 0 ) + , t_lastspike_( 0.0 ) +{ +} + +template < typename targetidentifierT > +void +stdp_facetshw_synapse_hom< 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::a_causal, a_causal_ ); + def< double >( d, names::a_acausal, a_acausal_ ); + def< double >( d, names::a_thresh_th, a_thresh_th_ ); + def< double >( d, names::a_thresh_tl, a_thresh_tl_ ); + + def< bool >( d, names::init_flag, init_flag_ ); + def< long >( d, names::synapse_id, synapse_id_ ); + def< double >( d, names::next_readout_time, next_readout_time_ ); + // useful to get conversion before activity, but weight_per_lut_entry_ not + // known here + // def(d, "discrete_weight", + // entry_to_weight_(weight_to_entry_(weight_, + // weight_per_lut_entry_), weight_per_lut_entry_)); +} + +template < typename targetidentifierT > +void +stdp_facetshw_synapse_hom< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) +{ + // base class properties + ConnectionBase::set_status( d, cm ); + updateValue< double >( d, names::weight, weight_ ); + + updateValue< double >( d, names::a_causal, a_causal_ ); + updateValue< double >( d, names::a_acausal, a_acausal_ ); + updateValue< double >( d, names::a_thresh_th, a_thresh_th_ ); + updateValue< double >( d, names::a_thresh_tl, a_thresh_tl_ ); + + updateValue< long >( d, names::synapse_id, synapse_id_ ); + + // TP: they should not be allowed to be changed! But needed for CopyModel ... + updateValue< bool >( d, names::init_flag, init_flag_ ); + updateValue< double >( d, names::next_readout_time, next_readout_time_ ); + + // setting discrete_weight_ does not make sense, is temporary variable +} + } // of namespace nest #endif // of #ifndef STDP_SYNAPSE_FACETSHW_HOM_H diff --git a/models/stdp_facetshw_synapse_hom_impl.h b/models/stdp_facetshw_synapse_hom_impl.h deleted file mode 100644 index 765b814715..0000000000 --- a/models/stdp_facetshw_synapse_hom_impl.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - * stdp_facetshw_synapse_hom_impl.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_SYNAPSE_FACETSHW_HOM_IMPL_H -#define STDP_SYNAPSE_FACETSHW_HOM_IMPL_H - -#include "stdp_facetshw_synapse_hom.h" - -// Includes from nestkernel: -#include "common_synapse_properties.h" -#include "connector_model.h" -#include "event.h" - -// Includes from sli: -#include "dictdatum.h" - -namespace nest -{ -// -// Implementation of class STDPFACETSHWHomCommonProperties. -// - -template < typename targetidentifierT > -STDPFACETSHWHomCommonProperties< targetidentifierT >::STDPFACETSHWHomCommonProperties() - : CommonSynapseProperties() - , tau_plus_( 20.0 ) - , tau_minus_( 20.0 ) - , Wmax_( 100.0 ) - , no_synapses_( 0 ) - , synapses_per_driver_( 50 ) // hardware efficiency of 50/256=20%, - // which is comparable to Fieres et al. (2008) - , driver_readout_time_( 15.0 ) // in ms; measured on hardware -{ - lookuptable_0_.resize( 16 ); - lookuptable_1_.resize( 16 ); - lookuptable_2_.resize( 16 ); - - // intermediate Guetig (mu=0.4) - // with r=4 bits and n=36 SSPs, see [3]_ - lookuptable_0_.at( 0 ) = 2; - lookuptable_0_.at( 1 ) = 3; - lookuptable_0_.at( 2 ) = 4; - lookuptable_0_.at( 3 ) = 4; - lookuptable_0_.at( 4 ) = 5; - lookuptable_0_.at( 5 ) = 6; - lookuptable_0_.at( 6 ) = 7; - lookuptable_0_.at( 7 ) = 8; - lookuptable_0_.at( 8 ) = 9; - lookuptable_0_.at( 9 ) = 10; - lookuptable_0_.at( 10 ) = 11; - lookuptable_0_.at( 11 ) = 12; - lookuptable_0_.at( 12 ) = 13; - lookuptable_0_.at( 13 ) = 14; - lookuptable_0_.at( 14 ) = 14; - lookuptable_0_.at( 15 ) = 15; - - lookuptable_1_.at( 0 ) = 0; - lookuptable_1_.at( 1 ) = 0; - lookuptable_1_.at( 2 ) = 1; - lookuptable_1_.at( 3 ) = 2; - lookuptable_1_.at( 4 ) = 3; - lookuptable_1_.at( 5 ) = 4; - lookuptable_1_.at( 6 ) = 5; - lookuptable_1_.at( 7 ) = 6; - lookuptable_1_.at( 8 ) = 7; - lookuptable_1_.at( 9 ) = 8; - lookuptable_1_.at( 10 ) = 9; - lookuptable_1_.at( 11 ) = 10; - lookuptable_1_.at( 12 ) = 10; - lookuptable_1_.at( 13 ) = 11; - lookuptable_1_.at( 14 ) = 12; - lookuptable_1_.at( 15 ) = 13; - - for ( size_t i = 0; i < lookuptable_0_.size(); ++i ) - { - lookuptable_2_.at( i ) = i; - } - - configbit_0_.resize( 4 ); - configbit_1_.resize( 4 ); - - // see [4]_ - configbit_0_.at( 0 ) = 0; - configbit_0_.at( 1 ) = 0; - configbit_0_.at( 2 ) = 1; - configbit_0_.at( 3 ) = 0; - configbit_1_.at( 0 ) = 0; - configbit_1_.at( 1 ) = 1; - configbit_1_.at( 2 ) = 0; - configbit_1_.at( 3 ) = 0; - - reset_pattern_.resize( 6 ); - for ( size_t i = 0; i < reset_pattern_.size(); ++i ) - { - reset_pattern_.at( i ) = true; - } - - weight_per_lut_entry_ = Wmax_ / ( lookuptable_0_.size() - 1 ); - calc_readout_cycle_duration_(); -} - -template < typename targetidentifierT > -void -STDPFACETSHWHomCommonProperties< targetidentifierT >::calc_readout_cycle_duration_() -{ - readout_cycle_duration_ = int( ( no_synapses_ - 1.0 ) / synapses_per_driver_ + 1.0 ) * driver_readout_time_; -} - -template < typename targetidentifierT > -void -STDPFACETSHWHomCommonProperties< targetidentifierT >::get_status( DictionaryDatum& d ) const -{ - CommonSynapseProperties::get_status( d ); - - def< double >( d, names::tau_plus, tau_plus_ ); - def< double >( d, names::tau_minus_stdp, tau_minus_ ); - def< double >( d, names::Wmax, Wmax_ ); - def< double >( d, names::weight_per_lut_entry, weight_per_lut_entry_ ); - - def< long >( d, names::no_synapses, no_synapses_ ); - def< long >( d, names::synapses_per_driver, synapses_per_driver_ ); - def< double >( d, names::driver_readout_time, driver_readout_time_ ); - def< double >( d, names::readout_cycle_duration, readout_cycle_duration_ ); - - ( *d )[ names::lookuptable_0 ] = IntVectorDatum( new std::vector< long >( lookuptable_0_ ) ); - ( *d )[ names::lookuptable_1 ] = IntVectorDatum( new std::vector< long >( lookuptable_1_ ) ); - ( *d )[ names::lookuptable_2 ] = IntVectorDatum( new std::vector< long >( lookuptable_2_ ) ); - ( *d )[ names::configbit_0 ] = IntVectorDatum( new std::vector< long >( configbit_0_ ) ); - ( *d )[ names::configbit_1 ] = IntVectorDatum( new std::vector< long >( configbit_1_ ) ); - ( *d )[ names::reset_pattern ] = IntVectorDatum( new std::vector< long >( reset_pattern_ ) ); -} - -template < typename targetidentifierT > -void -STDPFACETSHWHomCommonProperties< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) -{ - CommonSynapseProperties::set_status( d, cm ); - - updateValue< double >( d, names::tau_plus, tau_plus_ ); - updateValue< double >( d, names::tau_minus_stdp, tau_minus_ ); - if ( updateValue< double >( d, names::Wmax, Wmax_ ) ) - { - weight_per_lut_entry_ = Wmax_ / ( lookuptable_0_.size() - 1 ); - } - - // TP: they should not be allowed to be changed! But needed for CopyModel ... - updateValue< double >( d, names::weight_per_lut_entry, weight_per_lut_entry_ ); - updateValue< double >( d, names::readout_cycle_duration, readout_cycle_duration_ ); - if ( updateValue< long >( d, names::no_synapses, no_synapses_ ) ) - { - calc_readout_cycle_duration_(); - } - - if ( updateValue< long >( d, names::synapses_per_driver, synapses_per_driver_ ) ) - { - calc_readout_cycle_duration_(); - } - if ( updateValue< double >( d, names::driver_readout_time, driver_readout_time_ ) ) - { - calc_readout_cycle_duration_(); - } - - if ( d->known( names::lookuptable_0 ) ) - { - updateValue< std::vector< long > >( d, names::lookuptable_0, lookuptable_0_ ); - - // right size? - if ( lookuptable_0_.size() != lookuptable_1_.size() ) - { - throw BadProperty( "Look-up table has not 2^4 entries!" ); - } - - // are look-up table entries out of bounds? - for ( size_t i = 0; i < size_t( lookuptable_0_.size() ); ++i ) - { - if ( lookuptable_0_[ i ] < 0 or lookuptable_0_[ i ] > 15 ) - { - throw BadProperty( "Look-up table entries must be integers in [0,15]" ); - } - } - } - if ( d->known( names::lookuptable_1 ) ) - { - updateValue< std::vector< long > >( d, names::lookuptable_1, lookuptable_1_ ); - - // right size? - if ( lookuptable_1_.size() != lookuptable_0_.size() ) - { - throw BadProperty( "Look-up table has not 2^4 entries!" ); - } - - // are look-up table entries out of bounds? - for ( size_t i = 0; i < size_t( lookuptable_1_.size() ); ++i ) - { - if ( lookuptable_1_[ i ] < 0 or lookuptable_1_[ i ] > 15 ) - { - throw BadProperty( "Look-up table entries must be integers in [0,15]" ); - } - } - } - if ( d->known( names::lookuptable_2 ) ) - { - updateValue< std::vector< long > >( d, names::lookuptable_2, lookuptable_2_ ); - - // right size? - if ( lookuptable_2_.size() != lookuptable_0_.size() ) - { - throw BadProperty( "Look-up table has not 2^4 entries!" ); - } - - // are look-up table entries out of bounds? - for ( size_t i = 0; i < size_t( lookuptable_2_.size() ); ++i ) - { - if ( lookuptable_2_[ i ] < 0 or lookuptable_2_[ i ] > 15 ) - { - throw BadProperty( "Look-up table entries must be integers in [0,15]" ); - } - } - } - - if ( d->known( names::configbit_0 ) ) - { - updateValue< std::vector< long > >( d, names::configbit_0, configbit_0_ ); - - // right size? - if ( configbit_0_.size() != 4 ) - { - throw BadProperty( "Wrong number of configuration bits (!=4)." ); - } - } - if ( d->known( names::configbit_1 ) ) - { - updateValue< std::vector< long > >( d, names::configbit_1, configbit_1_ ); - - // right size? - if ( configbit_1_.size() != 4 ) - { - throw BadProperty( "Wrong number of configuration bits (!=4)." ); - } - } - if ( d->known( names::reset_pattern ) ) - { - updateValue< std::vector< long > >( d, names::reset_pattern, reset_pattern_ ); - - // right size? - if ( reset_pattern_.size() != 6 ) - { - throw BadProperty( "Wrong number of reset bits (!=6)." ); - } - } -} - - -// -// Implementation of class stdp_facetshw_synapse_hom. -// -template < typename targetidentifierT > -stdp_facetshw_synapse_hom< targetidentifierT >::stdp_facetshw_synapse_hom() - : weight_( 1.0 ) - , a_causal_( 0.0 ) - , a_acausal_( 0.0 ) - , a_thresh_th_( 21.835 ) - , a_thresh_tl_( 21.835 ) // exp(-10ms/20ms) * 36SSPs - , init_flag_( false ) - , synapse_id_( 0 ) - , next_readout_time_( 0.0 ) - , discrete_weight_( 0 ) - , t_lastspike_( 0.0 ) -{ -} - -template < typename targetidentifierT > -void -stdp_facetshw_synapse_hom< 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::a_causal, a_causal_ ); - def< double >( d, names::a_acausal, a_acausal_ ); - def< double >( d, names::a_thresh_th, a_thresh_th_ ); - def< double >( d, names::a_thresh_tl, a_thresh_tl_ ); - - def< bool >( d, names::init_flag, init_flag_ ); - def< long >( d, names::synapse_id, synapse_id_ ); - def< double >( d, names::next_readout_time, next_readout_time_ ); - // useful to get conversion before activity, but weight_per_lut_entry_ not - // known here - // def(d, "discrete_weight", - // entry_to_weight_(weight_to_entry_(weight_, - // weight_per_lut_entry_), weight_per_lut_entry_)); -} - -template < typename targetidentifierT > -void -stdp_facetshw_synapse_hom< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) -{ - // base class properties - ConnectionBase::set_status( d, cm ); - updateValue< double >( d, names::weight, weight_ ); - - updateValue< double >( d, names::a_causal, a_causal_ ); - updateValue< double >( d, names::a_acausal, a_acausal_ ); - updateValue< double >( d, names::a_thresh_th, a_thresh_th_ ); - updateValue< double >( d, names::a_thresh_tl, a_thresh_tl_ ); - - updateValue< long >( d, names::synapse_id, synapse_id_ ); - - // TP: they should not be allowed to be changed! But needed for CopyModel ... - updateValue< bool >( d, names::init_flag, init_flag_ ); - updateValue< double >( d, names::next_readout_time, next_readout_time_ ); - - // setting discrete_weight_ does not make sense, is temporary variable -} - -} // of namespace nest - -#endif // #ifndef STDP_SYNAPSE_FACETSHW_HOM_IMPL_H diff --git a/models/stdp_nn_pre_centered_synapse.cpp b/models/stdp_nn_pre_centered_synapse.cpp index baa03ddfa5..99041c8e28 100644 --- a/models/stdp_nn_pre_centered_synapse.cpp +++ b/models/stdp_nn_pre_centered_synapse.cpp @@ -22,9 +22,6 @@ #include "stdp_nn_pre_centered_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_stdp_nn_pre_centered_synapse( const std::string& name ) { diff --git a/models/stdp_nn_restr_synapse.cpp b/models/stdp_nn_restr_synapse.cpp index c531ac5c38..1ba4d3f729 100644 --- a/models/stdp_nn_restr_synapse.cpp +++ b/models/stdp_nn_restr_synapse.cpp @@ -22,9 +22,6 @@ #include "stdp_nn_restr_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_stdp_nn_restr_synapse( const std::string& name ) { diff --git a/models/stdp_nn_symm_synapse.cpp b/models/stdp_nn_symm_synapse.cpp index b1b69b3b26..85ca3c5b4c 100644 --- a/models/stdp_nn_symm_synapse.cpp +++ b/models/stdp_nn_symm_synapse.cpp @@ -22,9 +22,6 @@ #include "stdp_nn_symm_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_stdp_nn_symm_synapse( const std::string& name ) { diff --git a/models/stdp_pl_synapse_hom.cpp b/models/stdp_pl_synapse_hom.cpp index 3bc6a0c247..f9eb393d9a 100644 --- a/models/stdp_pl_synapse_hom.cpp +++ b/models/stdp_pl_synapse_hom.cpp @@ -24,9 +24,7 @@ // 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" diff --git a/models/stdp_synapse.cpp b/models/stdp_synapse.cpp index cbd48650ad..63fe836e86 100644 --- a/models/stdp_synapse.cpp +++ b/models/stdp_synapse.cpp @@ -22,9 +22,6 @@ #include "stdp_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_stdp_synapse( const std::string& name ) { diff --git a/models/stdp_synapse_hom.cpp b/models/stdp_synapse_hom.cpp index fccdf1b148..fb23eefe80 100644 --- a/models/stdp_synapse_hom.cpp +++ b/models/stdp_synapse_hom.cpp @@ -24,8 +24,6 @@ // Includes from nestkernel: #include "common_synapse_properties.h" -#include "connector_model.h" -#include "nest_impl.h" // Includes from sli: #include "dictdatum.h" diff --git a/models/stdp_triplet_synapse.cpp b/models/stdp_triplet_synapse.cpp index 597c1ee9c6..28bd3fadd4 100644 --- a/models/stdp_triplet_synapse.cpp +++ b/models/stdp_triplet_synapse.cpp @@ -22,9 +22,6 @@ #include "stdp_triplet_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_stdp_triplet_synapse( const std::string& name ) { diff --git a/models/step_current_generator.cpp b/models/step_current_generator.cpp index d006dc30af..ee7c852b4e 100644 --- a/models/step_current_generator.cpp +++ b/models/step_current_generator.cpp @@ -23,10 +23,7 @@ #include "step_current_generator.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "booldatum.h" diff --git a/models/step_rate_generator.cpp b/models/step_rate_generator.cpp index dfe104987d..f6ba8c432e 100644 --- a/models/step_rate_generator.cpp +++ b/models/step_rate_generator.cpp @@ -23,10 +23,7 @@ #include "step_rate_generator.h" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "nest_impl.h" -#include "universal_data_logger_impl.h" // Includes from sli: #include "booldatum.h" diff --git a/models/tanh_rate.cpp b/models/tanh_rate.cpp index c1a41cb679..fccc105446 100644 --- a/models/tanh_rate.cpp +++ b/models/tanh_rate.cpp @@ -22,10 +22,7 @@ #include "tanh_rate.h" -// Includes from nestkernel -#include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include namespace nest { diff --git a/models/tanh_rate.h b/models/tanh_rate.h index ce04f718b2..b8b4e599df 100644 --- a/models/tanh_rate.h +++ b/models/tanh_rate.h @@ -25,11 +25,8 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_neuron_opn.h" -#include "rate_neuron_opn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" namespace nest { diff --git a/models/threshold_lin_rate.cpp b/models/threshold_lin_rate.cpp index dbb877601e..cb054d7a52 100644 --- a/models/threshold_lin_rate.cpp +++ b/models/threshold_lin_rate.cpp @@ -22,10 +22,7 @@ #include "threshold_lin_rate.h" -// Includes from nestkernel -#include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" +#include namespace nest { diff --git a/models/threshold_lin_rate.h b/models/threshold_lin_rate.h index 2329f4064a..4c1dbeeea2 100644 --- a/models/threshold_lin_rate.h +++ b/models/threshold_lin_rate.h @@ -28,11 +28,8 @@ // Includes from models: #include "rate_neuron_ipn.h" -#include "rate_neuron_ipn_impl.h" #include "rate_neuron_opn.h" -#include "rate_neuron_opn_impl.h" #include "rate_transformer_node.h" -#include "rate_transformer_node_impl.h" namespace nest { diff --git a/models/tsodyks2_synapse.cpp b/models/tsodyks2_synapse.cpp index 0019c0b11f..95c5abbc32 100644 --- a/models/tsodyks2_synapse.cpp +++ b/models/tsodyks2_synapse.cpp @@ -22,9 +22,6 @@ #include "tsodyks2_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_tsodyks2_synapse( const std::string& name ) { diff --git a/models/tsodyks_synapse.cpp b/models/tsodyks_synapse.cpp index 19e2222ae9..8a0bd64960 100644 --- a/models/tsodyks_synapse.cpp +++ b/models/tsodyks_synapse.cpp @@ -22,9 +22,6 @@ #include "tsodyks_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_tsodyks_synapse( const std::string& name ) { diff --git a/models/tsodyks_synapse_hom.cpp b/models/tsodyks_synapse_hom.cpp index 65e450ba2b..caec1959f1 100644 --- a/models/tsodyks_synapse_hom.cpp +++ b/models/tsodyks_synapse_hom.cpp @@ -22,10 +22,6 @@ #include "tsodyks_synapse_hom.h" -// Includes from nestkernel: -#include "connector_model.h" -#include "nest_impl.h" - void nest::register_tsodyks_synapse_hom( const std::string& name ) { diff --git a/models/urbanczik_synapse.cpp b/models/urbanczik_synapse.cpp index 8fd26b8550..e698e72f0f 100644 --- a/models/urbanczik_synapse.cpp +++ b/models/urbanczik_synapse.cpp @@ -22,9 +22,6 @@ #include "urbanczik_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_urbanczik_synapse( const std::string& name ) { diff --git a/models/vogels_sprekeler_synapse.cpp b/models/vogels_sprekeler_synapse.cpp index e1279d0888..989aec0e75 100644 --- a/models/vogels_sprekeler_synapse.cpp +++ b/models/vogels_sprekeler_synapse.cpp @@ -22,9 +22,6 @@ #include "vogels_sprekeler_synapse.h" -// Includes from nestkernel: -#include "nest_impl.h" - void nest::register_vogels_sprekeler_synapse( const std::string& name ) { diff --git a/models/volume_transmitter.cpp b/models/volume_transmitter.cpp index 659838b288..69f048a03e 100644 --- a/models/volume_transmitter.cpp +++ b/models/volume_transmitter.cpp @@ -24,11 +24,7 @@ // Includes from nestkernel: -#include "connector_base.h" -#include "exceptions.h" #include "kernel_manager.h" -#include "model_manager_impl.h" -#include "nest_impl.h" #include "spikecounter.h" // Includes from libnestutil: diff --git a/models/weight_recorder.cpp b/models/weight_recorder.cpp index 33f1fef67d..cd1f9f434d 100644 --- a/models/weight_recorder.cpp +++ b/models/weight_recorder.cpp @@ -27,12 +27,11 @@ #include "compose.hpp" // Includes from nestkernel: -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "model_manager_impl.h" +#include "nest.h" #include "nest_datums.h" -#include "nest_impl.h" #include "node_collection.h" +#include "node_manager.h" // Includes from sli: #include "arraydatum.h" diff --git a/models/weight_recorder.h b/models/weight_recorder.h index ef23ad8f6d..fbff6d2a64 100644 --- a/models/weight_recorder.h +++ b/models/weight_recorder.h @@ -23,14 +23,10 @@ #ifndef WEIGHT_RECORDER_H #define WEIGHT_RECORDER_H -// C++ includes: -#include - // Includes from nestkernel: -#include "device_node.h" #include "event.h" #include "exceptions.h" -#include "kernel_manager.h" +#include "nest_datums.h" #include "nest_types.h" #include "recording_device.h" diff --git a/nestkernel/CMakeLists.txt b/nestkernel/CMakeLists.txt index ab3257a89f..f54a0aaccd 100644 --- a/nestkernel/CMakeLists.txt +++ b/nestkernel/CMakeLists.txt @@ -18,21 +18,21 @@ # along with NEST. If not, see . set ( nestkernel_sources - universal_data_logger_impl.h universal_data_logger.h + universal_data_logger.h recordables_map.h archiving_node.h archiving_node.cpp clopath_archiving_node.h clopath_archiving_node.cpp - urbanczik_archiving_node.h urbanczik_archiving_node_impl.h - eprop_archiving_node.h eprop_archiving_node_impl.h + urbanczik_archiving_node.h + eprop_archiving_node.h eprop_archiving_node_readout.h - eprop_archiving_node_recurrent.h eprop_archiving_node_recurrent_impl.h + eprop_archiving_node_recurrent.h common_synapse_properties.h common_synapse_properties.cpp connection.h connection_label.h common_properties_hom_w.h syn_id_delay.h - connector_base.h connector_base_impl.h - connector_model.h connector_model_impl.h connector_model.cpp + connector_base.h connector_base.cpp + connector_model.h connector_model.cpp connector_model_impl.h connection_id.h connection_id.cpp deprecation_warning.h deprecation_warning.cpp device.h device.cpp @@ -40,12 +40,12 @@ set ( nestkernel_sources module_manager.h module_manager.cpp event.h event.cpp exceptions.h exceptions.cpp - genericmodel.h genericmodel_impl.h + genericmodel.h node_collection.h node_collection.cpp generic_factory.h histentry.h histentry.cpp model.h model.cpp - model_manager.h model_manager_impl.h model_manager.cpp + model_manager.h model_manager.cpp nest_datums.h nest_datums.cpp nest_names.cpp nest_names.h nestmodule.h nestmodule.cpp @@ -60,35 +60,35 @@ set ( nestkernel_sources random_generators.h recording_device.h recording_device.cpp pseudo_recording_device.h - ring_buffer.h ring_buffer_impl.h ring_buffer.cpp - secondary_event.h secondary_event_impl.h + ring_buffer.h ring_buffer.cpp + secondary_event.h slice_ring_buffer.cpp slice_ring_buffer.h spikecounter.h spikecounter.cpp stimulation_device.h stimulation_device.cpp target_identifier.h sparse_node_array.h sparse_node_array.cpp conn_parameter.h conn_parameter.cpp - conn_builder.h conn_builder_impl.h conn_builder.cpp + conn_builder.h conn_builder.cpp conn_builder_factory.h conn_builder_conngen.h conn_builder_conngen.cpp sonata_connector.h sonata_connector.cpp music_event_handler.h music_event_handler.cpp music_rate_in_handler.h music_rate_in_handler.cpp music_manager.cpp music_manager.h - nest.h nest_impl.h nest.cpp + nest.h nest.cpp synaptic_element.h synaptic_element.cpp growth_curve.h growth_curve.cpp growth_curve_factory.h kernel_manager.h kernel_manager.cpp - vp_manager.h vp_manager_impl.h vp_manager.cpp - io_manager.h io_manager_impl.h io_manager.cpp - mpi_manager.h mpi_manager_impl.h mpi_manager.cpp + vp_manager.h vp_manager.cpp + io_manager.h io_manager.cpp + mpi_manager.h mpi_manager.cpp simulation_manager.h simulation_manager.cpp - connection_manager.h connection_manager_impl.h connection_manager.cpp - sp_manager.h sp_manager_impl.h sp_manager.cpp + connection_manager.h connection_manager.cpp + sp_manager.h sp_manager.cpp delay_checker.h delay_checker.cpp random_manager.h random_manager.cpp - event_delivery_manager.h event_delivery_manager_impl.h + event_delivery_manager.h event_delivery_manager.cpp node_manager.h node_manager.cpp logging_manager.h logging_manager.cpp @@ -98,7 +98,7 @@ set ( nestkernel_sources recording_backend_screen.h recording_backend_screen.cpp manager_interface.h target_table.h target_table.cpp - target_table_devices.h target_table_devices.cpp target_table_devices_impl.h + target_table_devices.h target_table_devices.cpp target.h target_data.h static_assert.h send_buffer_position.h send_buffer_position.cpp source.h @@ -106,19 +106,19 @@ set ( nestkernel_sources source_table_position.h spike_data.h structural_plasticity_node.h structural_plasticity_node.cpp - connection_creator.h connection_creator.cpp connection_creator_impl.h + connection_creator.h connection_creator.cpp free_layer.h grid_layer.h grid_mask.h layer.h layer.cpp layer_impl.h - mask.h mask.cpp mask_impl.h - ntree.h ntree_impl.h + mask.h mask.cpp + ntree.h position.h spatial.h spatial.cpp stimulation_backend.h buffer_resize_log.h buffer_resize_log.cpp nest_extension_interface.h - stopwatch.h stopwatch_impl.h + stopwatch.h ) diff --git a/nestkernel/archiving_node.cpp b/nestkernel/archiving_node.cpp index 7ad511eb3c..ba35130aa1 100644 --- a/nestkernel/archiving_node.cpp +++ b/nestkernel/archiving_node.cpp @@ -23,6 +23,7 @@ #include "archiving_node.h" // Includes from nestkernel: +#include "connection_manager.h" #include "kernel_manager.h" // Includes from sli: diff --git a/nestkernel/buffer_resize_log.cpp b/nestkernel/buffer_resize_log.cpp index a37e383c7a..948766245b 100644 --- a/nestkernel/buffer_resize_log.cpp +++ b/nestkernel/buffer_resize_log.cpp @@ -23,8 +23,10 @@ #include "buffer_resize_log.h" // Includes from nestkernel: +#include "dictutils.h" #include "kernel_manager.h" #include "nest_names.h" +#include "simulation_manager.h" namespace nest { diff --git a/nestkernel/clopath_archiving_node.cpp b/nestkernel/clopath_archiving_node.cpp index 42bb957ea2..07f3e30038 100644 --- a/nestkernel/clopath_archiving_node.cpp +++ b/nestkernel/clopath_archiving_node.cpp @@ -23,6 +23,7 @@ #include "clopath_archiving_node.h" // Includes from nestkernel: +#include "connection_manager.h" #include "kernel_manager.h" // Includes from sli: diff --git a/nestkernel/common_properties_hom_w.h b/nestkernel/common_properties_hom_w.h index b5b8d16879..527568cb25 100644 --- a/nestkernel/common_properties_hom_w.h +++ b/nestkernel/common_properties_hom_w.h @@ -25,6 +25,8 @@ // Includes from nestkernel: #include "common_synapse_properties.h" +#include "dictutils.h" +#include "nest_names.h" namespace nest { diff --git a/nestkernel/common_synapse_properties.cpp b/nestkernel/common_synapse_properties.cpp index 2a5053c0c3..6bb03a4f6b 100644 --- a/nestkernel/common_synapse_properties.cpp +++ b/nestkernel/common_synapse_properties.cpp @@ -24,9 +24,8 @@ // Includes from nestkernel: #include "connector_model.h" -#include "nest_timeconverter.h" -#include "nest_types.h" #include "node.h" +#include "node_manager.h" // Includes from models: #include "weight_recorder.h" diff --git a/nestkernel/common_synapse_properties.h b/nestkernel/common_synapse_properties.h index fab02945c6..256cf92c16 100644 --- a/nestkernel/common_synapse_properties.h +++ b/nestkernel/common_synapse_properties.h @@ -23,12 +23,6 @@ #ifndef COMMON_SYNAPSE_PROPERTIES_H #define COMMON_SYNAPSE_PROPERTIES_H -// Includes from nestkernel: -#include "connector_model.h" -#include "nest_datums.h" -#include "nest_types.h" -#include "node.h" - // Includes from sli: #include "dictdatum.h" @@ -38,8 +32,8 @@ namespace nest // forward declarations class weight_recorder; -class ConnectorModel; class TimeConverter; +class ConnectorModel; /** * Class containing the common properties for all connections of a certain type. diff --git a/nestkernel/conn_builder.cpp b/nestkernel/conn_builder.cpp index f70f00f0b4..1169651b38 100644 --- a/nestkernel/conn_builder.cpp +++ b/nestkernel/conn_builder.cpp @@ -26,14 +26,17 @@ #include "logging.h" // Includes from nestkernel: -#include "conn_builder_impl.h" #include "conn_parameter.h" #include "connection_manager.h" #include "exceptions.h" #include "kernel_manager.h" +#include "logging_manager.h" +#include "model_manager.h" +#include "nest.h" #include "nest_names.h" #include "node.h" -#include "vp_manager_impl.h" +#include "node_manager.h" +#include "random_manager.h" // Includes from sli: #include "dict.h" diff --git a/nestkernel/conn_builder.h b/nestkernel/conn_builder.h index 801d4bb355..4e24c7a60b 100644 --- a/nestkernel/conn_builder.h +++ b/nestkernel/conn_builder.h @@ -40,9 +40,10 @@ // Includes from nestkernel: #include "conn_parameter.h" -#include "nest_time.h" +#include "kernel_manager.h" #include "node_collection.h" #include "parameter.h" +#include "sp_manager.h" // Includes from sli: #include "dictdatum.h" @@ -860,6 +861,20 @@ BipartiteConnBuilder::skip_conn_parameter_( size_t target_thread, size_t n_skip } } +inline void +BipartiteConnBuilder::single_disconnect_( size_t snode_id, Node& target, size_t target_thread ) +{ + // index tnode_id = target.get_node_id(); + // This is the most simple case in which only the synapse_model_ has been + // defined. TODO: Add functionality to delete synapses with a given weight + // or a given delay + if ( synapse_model_id_.size() > 1 ) + { + throw KernelException( "Can only disconnect when single element syn_spec has been used." ); + } + kernel().sp_manager.disconnect( snode_id, &target, target_thread, synapse_model_id_[ 0 ] ); +} + } // namespace nest #endif diff --git a/nestkernel/conn_builder_impl.h b/nestkernel/conn_builder_impl.h deleted file mode 100644 index 385bb12ec8..0000000000 --- a/nestkernel/conn_builder_impl.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * conn_builder_impl.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 CONN_BUILDER_IMPL_H -#define CONN_BUILDER_IMPL_H - -#include "conn_builder.h" - -// Includes from nestkernel: -#include "kernel_manager.h" -#include "nest_names.h" - -namespace nest -{ - -inline void -BipartiteConnBuilder::single_disconnect_( size_t snode_id, Node& target, size_t target_thread ) -{ - // index tnode_id = target.get_node_id(); - // This is the most simple case in which only the synapse_model_ has been - // defined. TODO: Add functionality to delete synapses with a given weight - // or a given delay - if ( synapse_model_id_.size() > 1 ) - { - throw KernelException( "Can only disconnect when single element syn_spec has been used." ); - } - kernel().sp_manager.disconnect( snode_id, &target, target_thread, synapse_model_id_[ 0 ] ); -} - -} // namespace nest - -#endif /* CONN_BUILDER_IMPL_H */ diff --git a/nestkernel/connection.h b/nestkernel/connection.h index 4a90eb2f0f..ddec70f6bb 100644 --- a/nestkernel/connection.h +++ b/nestkernel/connection.h @@ -26,7 +26,6 @@ // Includes from nestkernel: #include "common_synapse_properties.h" #include "connection_label.h" -#include "connector_base_impl.h" #include "delay_checker.h" #include "event.h" #include "kernel_manager.h" diff --git a/nestkernel/connection_creator.h b/nestkernel/connection_creator.h index 62d2671344..087e5f43a8 100644 --- a/nestkernel/connection_creator.h +++ b/nestkernel/connection_creator.h @@ -27,9 +27,12 @@ #include // Includes from nestkernel: +#include "connection_manager.h" #include "kernel_manager.h" +#include "nest.h" #include "nest_names.h" #include "nestmodule.h" +#include "node_manager.h" // Includes from spatial: #include "mask.h" @@ -188,6 +191,870 @@ class ConnectionCreator std::vector< std::shared_ptr< Parameter > > delay_; }; +template < int D > +void +ConnectionCreator::connect( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + switch ( type_ ) + { + case Pairwise_bernoulli_on_source: + + pairwise_bernoulli_on_source_( source, source_nc, target, target_nc ); + break; + + case Fixed_indegree: + + fixed_indegree_( source, source_nc, target, target_nc ); + break; + + case Fixed_outdegree: + + fixed_outdegree_( source, source_nc, target, target_nc ); + break; + + case Pairwise_bernoulli_on_target: + + pairwise_bernoulli_on_target_( source, source_nc, target, target_nc ); + break; + + case Pairwise_poisson: + + pairwise_poisson_( source, source_nc, target, target_nc ); + break; + + default: + throw BadProperty( "Unknown connection type." ); + } +} + +template < typename Iterator, int D > +void +ConnectionCreator::connect_to_target_( Iterator from, + Iterator to, + Node* tgt_ptr, + const Position< D >& tgt_pos, + size_t tgt_thread, + const Layer< D >& source ) +{ + RngPtr rng = get_vp_specific_rng( tgt_thread ); + + // We create a source pos vector here that can be updated with the + // source position. This is done to avoid creating and destroying + // unnecessarily many vectors. + std::vector< double > source_pos( D ); + const std::vector< double > target_pos = tgt_pos.get_vector(); + + for ( Iterator iter = from; iter != to; ++iter ) + { + if ( not allow_autapses_ and ( iter->second == tgt_ptr->get_node_id() ) ) + { + continue; + } + iter->first.get_vector( source_pos ); + + if ( not kernel_ or rng->drand() < kernel_->value( rng, source_pos, target_pos, source, tgt_ptr ) ) + { + for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) + { + kernel().connection_manager.connect( iter->second, + tgt_ptr, + tgt_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ tgt_thread ], + delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); + } + } + } +} + +template < typename Iterator, int D > +void +ConnectionCreator::connect_to_target_poisson_( Iterator from, + Iterator to, + Node* tgt_ptr, + const Position< D >& tgt_pos, + size_t tgt_thread, + const Layer< D >& source ) +{ + RngPtr rng = get_vp_specific_rng( tgt_thread ); + + // We create a source pos vector here that can be updated with the + // source position. This is done to avoid creating and destroying + // unnecessarily many vectors. + std::vector< double > source_pos( D ); + const std::vector< double > target_pos = tgt_pos.get_vector(); + poisson_distribution poi_dist; + + for ( Iterator iter = from; iter != to; ++iter ) + { + if ( not allow_autapses_ and ( iter->second == tgt_ptr->get_node_id() ) ) + { + continue; + } + iter->first.get_vector( source_pos ); + + // Sample number of connections that are to be established + poisson_distribution::param_type param( kernel_->value( rng, source_pos, target_pos, source, tgt_ptr ) ); + const unsigned long num_conns = poi_dist( rng, param ); + for ( unsigned long conn_counter = 0; conn_counter < num_conns; ++conn_counter ) + { + for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) + { + kernel().connection_manager.connect( iter->second, + tgt_ptr, + tgt_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ tgt_thread ], + delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), + weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); + } + } + } +} + +template < int D > +ConnectionCreator::PoolWrapper_< D >::PoolWrapper_() + : masked_layer_( 0 ) + , positions_( 0 ) +{ +} + +template < int D > +ConnectionCreator::PoolWrapper_< D >::~PoolWrapper_< D >() +{ + if ( masked_layer_ ) + { + delete masked_layer_; + } +} + +template < int D > +void +ConnectionCreator::PoolWrapper_< D >::define( MaskedLayer< D >* ml ) +{ + assert( masked_layer_ == 0 ); + assert( positions_ == 0 ); + assert( ml != 0 ); + masked_layer_ = ml; +} + +template < int D > +void +ConnectionCreator::PoolWrapper_< D >::define( std::vector< std::pair< Position< D >, size_t > >* pos ) +{ + assert( masked_layer_ == 0 ); + assert( positions_ == 0 ); + assert( pos != 0 ); + positions_ = pos; +} + +template < int D > +typename Ntree< D, size_t >::masked_iterator +ConnectionCreator::PoolWrapper_< D >::masked_begin( const Position< D >& pos ) const +{ + return masked_layer_->begin( pos ); +} + +template < int D > +typename Ntree< D, size_t >::masked_iterator +ConnectionCreator::PoolWrapper_< D >::masked_end() const +{ + return masked_layer_->end(); +} + +template < int D > +typename std::vector< std::pair< Position< D >, size_t > >::iterator +ConnectionCreator::PoolWrapper_< D >::begin() const +{ + return positions_->begin(); +} + +template < int D > +typename std::vector< std::pair< Position< D >, size_t > >::iterator +ConnectionCreator::PoolWrapper_< D >::end() const +{ + return positions_->end(); +} + + +template < int D > +void +ConnectionCreator::pairwise_bernoulli_on_source_( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + // Connect using pairwise Bernoulli drawing source nodes (target driven) + // For each local target node: + // 1. Apply Mask to source layer + // 2. For each source node: Compute probability, draw random number, make + // connection conditionally + + // retrieve global positions, either for masked or unmasked pool + PoolWrapper_< D > pool; + if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor + { + pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, source_nc ) ); + } + else + { + pool.define( source.get_global_positions_vector( source_nc ) ); + } + + std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); + +#pragma omp parallel + { + const int thread_id = kernel().vp_manager.get_thread_id(); + try + { + 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 ) + { + Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); + + if ( not tgt->is_proxy() ) + { + const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); + + if ( mask_.get() ) + { + connect_to_target_( + pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, source ); + } + else + { + connect_to_target_( pool.begin(), pool.end(), tgt, target_pos, thread_id, source ); + } + } + } // for target_begin + } + catch ( std::exception& err ) + { + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( thread_id ) = + std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + } + } // omp parallel + // check if any exceptions have been raised + for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) + { + if ( exceptions_raised_.at( thr ).get() ) + { + throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); + } + } +} + + +template < int D > +void +ConnectionCreator::pairwise_bernoulli_on_target_( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + // Connecting using pairwise Bernoulli drawing target nodes (source driven) + // It is actually implemented as pairwise Bernoulli on source nodes, + // but with displacements computed in the target layer. The Mask has been + // reversed so that it can be applied to the source instead of the target. + // For each local target node: + // 1. Apply (Converse)Mask to source layer + // 2. For each source node: Compute probability, draw random number, make + // connection conditionally + + PoolWrapper_< D > pool; + if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor + { + // By supplying the target layer to the MaskedLayer constructor, the + // mask is mirrored so it may be applied to the source layer instead + pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, target, source_nc ) ); + } + else + { + pool.define( source.get_global_positions_vector( source_nc ) ); + } + + std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); + + // We only need to check the first in the NodeCollection + Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); + if ( not first_in_tgt->has_proxies() ) + { + throw IllegalConnection( "Spatial Connect with pairwise_bernoulli to devices is not possible." ); + } + +#pragma omp parallel + { + const int thread_id = kernel().vp_manager.get_thread_id(); + try + { + 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 ) + { + Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); + + assert( not tgt->is_proxy() ); + + const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); + + if ( mask_.get() ) + { + // We do the same as in the target driven case, except that we calculate displacements in the target layer. + // We therefore send in target as last parameter. + connect_to_target_( pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, target ); + } + else + { + // We do the same as in the target driven case, except that we calculate displacements in the target layer. + // We therefore send in target as last parameter. + connect_to_target_( pool.begin(), pool.end(), tgt, target_pos, thread_id, target ); + } + + } // end for + } + catch ( std::exception& err ) + { + // We must create a new exception here, err's lifetime ends at the end of the catch block. + exceptions_raised_.at( thread_id ) = + std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + } + } // omp parallel + // check if any exceptions have been raised + for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) + { + if ( exceptions_raised_.at( thr ).get() ) + { + throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); + } + } +} + + +template < int D > +void +ConnectionCreator::pairwise_poisson_( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + // Connect using pairwise Poisson drawing source nodes (target driven) + // For each local target node: + // 1. Apply Mask to source layer + // 2. For each source node: Compute probability, draw random number, make + // connection conditionally + + // retrieve global positions, either for masked or unmasked pool + PoolWrapper_< D > pool; + if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor + { + pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, source_nc ) ); + } + else + { + pool.define( source.get_global_positions_vector( source_nc ) ); + } + + std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); + +#pragma omp parallel + { + const int thread_id = kernel().vp_manager.get_thread_id(); + try + { + 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 ) + { + Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); + + if ( not tgt->is_proxy() ) + { + const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); + + if ( mask_.get() ) + { + connect_to_target_poisson_( + pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, source ); + } + else + { + connect_to_target_poisson_( pool.begin(), pool.end(), tgt, target_pos, thread_id, source ); + } + } + } // for target_begin + } + catch ( std::exception& err ) + { + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( thread_id ) = + std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + } + } // omp parallel + // check if any exceptions have been raised + for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) + { + if ( exceptions_raised_.at( thr ).get() ) + { + throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); + } + } +} + + +template < int D > +void +ConnectionCreator::fixed_indegree_( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + // fixed_indegree connections (fixed fan in) + // + // For each local target node: + // 1. Apply Mask to source layer + // 2. Compute connection probability for each source position + // 3. Draw source nodes and make connections + + // We only need to check the first in the NodeCollection + Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); + if ( not first_in_tgt->has_proxies() ) + { + throw IllegalConnection( "Spatial Connect with fixed_indegree to devices is not possible." ); + } + + NodeCollection::const_iterator target_begin = target_nc->rank_local_begin(); + NodeCollection::const_iterator target_end = target_nc->end(); + + // 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 ) + { + assert( not kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id )->is_proxy() ); + } + + if ( mask_.get() ) + { + MaskedLayer< D > masked_source( source, mask_, allow_oversized_, source_nc ); + const auto masked_source_end = masked_source.end(); + + std::vector< std::pair< Position< D >, size_t > > positions; + + 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 ); + + size_t target_thread = tgt->get_thread(); + RngPtr rng = get_vp_specific_rng( target_thread ); + Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); + + // We create a source pos vector here that can be updated with the + // source position. This is done to avoid creating and destroying + // unnecessarily many vectors. + std::vector< double > source_pos_vector( D ); + const std::vector< double > target_pos_vector = target_pos.get_vector(); + + unsigned long target_number_connections = + std::round( number_of_connections_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); + + // Get (position,node ID) pairs for sources inside mask + positions.resize( std::distance( masked_source.begin( target_pos ), masked_source_end ) ); + std::copy( masked_source.begin( target_pos ), masked_source_end, positions.begin() ); + + // We will select `number_of_connections_` sources within the mask. + // If there is no kernel, we can just draw uniform random numbers, + // but with a kernel we have to set up a probability distribution + // function using a discrete_distribution. + if ( kernel_ ) + { + + std::vector< double > probabilities; + probabilities.reserve( positions.size() ); + + // Collect probabilities for the sources + for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions.begin(); + iter != positions.end(); + ++iter ) + { + iter->first.get_vector( source_pos_vector ); + probabilities.push_back( kernel_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); + } + + if ( positions.empty() + or ( not allow_autapses_ and ( positions.size() == 1 ) and positions[ 0 ].second == target_id ) + or ( not allow_multapses_ and ( positions.size() < target_number_connections ) ) ) + { + std::string msg = String::compose( "Global target ID %1: Not enough sources found inside mask", target_id ); + throw KernelException( msg.c_str() ); + } + + // A discrete_distribution draws random integers with a non-uniform + // distribution. + discrete_distribution lottery; + const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); + lottery.param( param ); + + // If multapses are not allowed, we must keep track of which + // sources have been selected already. + std::vector< bool > is_selected( positions.size() ); + + // Draw `target_number_connections` sources + while ( target_number_connections > 0 ) + { + size_t random_id = lottery( rng ); + if ( not allow_multapses_ and is_selected[ random_id ] ) + { + continue; + } + + size_t source_id = positions[ random_id ].second; + if ( not allow_autapses_ and source_id == target_id ) + { + continue; + } + positions[ random_id ].first.get_vector( source_pos_vector ); + 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 ); + } + + is_selected[ random_id ] = true; + --target_number_connections; + } + } + else + { + + // no kernel + + if ( positions.empty() + or ( not allow_autapses_ and ( positions.size() == 1 ) and positions[ 0 ].second == target_id ) + or ( not allow_multapses_ and ( positions.size() < target_number_connections ) ) ) + { + std::string msg = String::compose( "Global target ID %1: Not enough sources found inside mask", target_id ); + throw KernelException( msg.c_str() ); + } + + // If multapses are not allowed, we must keep track of which + // sources have been selected already. + std::vector< bool > is_selected( positions.size() ); + + // Draw `target_number_connections` sources + while ( target_number_connections > 0 ) + { + const size_t random_id = rng->ulrand( positions.size() ); + if ( not allow_multapses_ and is_selected[ random_id ] ) + { + continue; + } + positions[ random_id ].first.get_vector( source_pos_vector ); + const size_t source_id = positions[ random_id ].second; + 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 ); + } + + is_selected[ random_id ] = true; + --target_number_connections; + } + } + } + } + else + { + // no mask + + // 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 ) + { + size_t target_id = ( *tgt_it ).node_id; + Node* const tgt = kernel().node_manager.get_node_or_proxy( target_id ); + size_t target_thread = tgt->get_thread(); + RngPtr rng = get_vp_specific_rng( target_thread ); + Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); + + unsigned long target_number_connections = std::round( number_of_connections_->value( rng, tgt ) ); + + std::vector< double > source_pos_vector( D ); + const std::vector< double > target_pos_vector = target_pos.get_vector(); + + if ( ( positions->size() == 0 ) + or ( not allow_autapses_ and ( positions->size() == 1 ) and ( ( *positions )[ 0 ].second == target_id ) ) + or ( not allow_multapses_ and ( positions->size() < target_number_connections ) ) ) + { + std::string msg = String::compose( "Global target ID %1: Not enough sources found", target_id ); + throw KernelException( msg.c_str() ); + } + + // We will select `target_number_connections` sources within the mask. + // If there is no kernel, we can just draw uniform random numbers, + // but with a kernel we have to set up a probability distribution + // function using a discrete_distribution. + if ( kernel_ ) + { + + std::vector< double > probabilities; + probabilities.reserve( positions->size() ); + + // Collect probabilities for the sources + for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions->begin(); + iter != positions->end(); + ++iter ) + { + iter->first.get_vector( source_pos_vector ); + probabilities.push_back( kernel_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); + } + + // A discrete_distribution draws random integers with a non-uniform + // distribution. + discrete_distribution lottery; + const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); + lottery.param( param ); + + // If multapses are not allowed, we must keep track of which + // sources have been selected already. + std::vector< bool > is_selected( positions->size() ); + + // Draw `target_number_connections` sources + while ( target_number_connections > 0 ) + { + const size_t random_id = lottery( rng ); + if ( not allow_multapses_ and is_selected[ random_id ] ) + { + continue; + } + + const size_t source_id = ( *positions )[ random_id ].second; + if ( not allow_autapses_ and source_id == target_id ) + { + continue; + } + + ( *positions )[ random_id ].first.get_vector( source_pos_vector ); + 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 ); + } + + is_selected[ random_id ] = true; + --target_number_connections; + } + } + else + { + + // no kernel + + // If multapses are not allowed, we must keep track of which + // sources have been selected already. + std::vector< bool > is_selected( positions->size() ); + + // Draw `target_number_connections` sources + while ( target_number_connections > 0 ) + { + const size_t random_id = rng->ulrand( positions->size() ); + if ( not allow_multapses_ and is_selected[ random_id ] ) + { + continue; + } + + const size_t source_id = ( *positions )[ random_id ].second; + if ( not allow_autapses_ and source_id == target_id ) + { + continue; + } + + ( *positions )[ random_id ].first.get_vector( source_pos_vector ); + 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 ); + } + + is_selected[ random_id ] = true; + --target_number_connections; + } + } + } + } +} + + +template < int D > +void +ConnectionCreator::fixed_outdegree_( Layer< D >& source, + NodeCollectionPTR source_nc, + Layer< D >& target, + NodeCollectionPTR target_nc ) +{ + // 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 + + // We only need to check the first in the NodeCollection + Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); + if ( not first_in_tgt->has_proxies() ) + { + throw IllegalConnection( "Spatial Connect with fixed_outdegree to devices is not possible." ); + } + + 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 ) + { + assert( not kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id )->is_proxy() ); + } + + // Fixed_outdegree connections (fixed fan out) + // + // For each (global) source: (All connections made on all mpi procs) + // 1. Apply mask to global targets + // 2. If using kernel: Compute connection probability for each global target + // 3. Draw connections to make using global rng + + MaskedLayer< D > masked_target( target, mask_, allow_oversized_, target_nc ); + const auto masked_target_end = masked_target.end(); + + // We create a target positions vector here that can be updated with the + // position and node ID pairs. This is done to avoid creating and destroying + // unnecessarily many vectors. + std::vector< std::pair< Position< D >, size_t > > target_pos_node_id_pairs; + std::vector< std::pair< Position< D >, size_t > > source_pos_node_id_pairs = + *source.get_global_positions_vector( source_nc ); + + for ( const auto& source_pos_node_id_pair : source_pos_node_id_pairs ) + { + const Position< D > source_pos = source_pos_node_id_pair.first; + const size_t source_id = source_pos_node_id_pair.second; + const auto src = kernel().node_manager.get_node_or_proxy( source_id ); + const std::vector< double > source_pos_vector = source_pos.get_vector(); + + // We create a target pos vector here that can be updated with the + // target position. This is done to avoid creating and destroying + // unnecessarily many vectors. + std::vector< double > target_pos_vector( D ); + std::vector< double > probabilities; + + // Find potential targets and probabilities + RngPtr grng = get_rank_synced_rng(); + target_pos_node_id_pairs.resize( std::distance( masked_target.begin( source_pos ), masked_target_end ) ); + std::copy( masked_target.begin( source_pos ), masked_target_end, target_pos_node_id_pairs.begin() ); + + probabilities.reserve( target_pos_node_id_pairs.size() ); + if ( kernel_ ) + { + for ( const auto& target_pos_node_id_pair : target_pos_node_id_pairs ) + { + // TODO: Why is probability calculated in source layer, but weight and delay in target layer? + target_pos_node_id_pair.first.get_vector( target_pos_vector ); + const auto tgt = kernel().node_manager.get_node_or_proxy( target_pos_node_id_pair.second ); + probabilities.push_back( kernel_->value( grng, source_pos_vector, target_pos_vector, source, tgt ) ); + } + } + else + { + probabilities.resize( target_pos_node_id_pairs.size(), 1.0 ); + } + + unsigned long number_of_connections = std::round( number_of_connections_->value( grng, src ) ); + + if ( target_pos_node_id_pairs.empty() + or ( not allow_multapses_ and target_pos_node_id_pairs.size() < number_of_connections ) ) + { + std::string msg = String::compose( "Global source ID %1: Not enough targets found", source_id ); + throw KernelException( msg.c_str() ); + } + + // Draw targets. A discrete_distribution draws random integers with a + // non-uniform distribution. + discrete_distribution lottery; + const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); + lottery.param( param ); + + // If multapses are not allowed, we must keep track of which + // targets have been selected already. + std::vector< bool > is_selected( target_pos_node_id_pairs.size() ); + + // Draw `number_of_connections` targets + while ( number_of_connections > 0 ) + { + const size_t random_id = lottery( get_rank_synced_rng() ); + if ( not allow_multapses_ and is_selected[ random_id ] ) + { + continue; + } + const size_t target_id = target_pos_node_id_pairs[ random_id ].second; + if ( not allow_autapses_ and source_id == target_id ) + { + continue; + } + + is_selected[ random_id ] = true; + + target_pos_node_id_pairs[ random_id ].first.get_vector( target_pos_vector ); + + std::vector< double > rng_weight_vec; + std::vector< double > rng_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 ) ); + } + + // Each VP has now decided to create this connection and drawn any random parameter values + // required for it. Each VP thus counts the connection as created, but only the VP hosting the + // target neuron actually creates the connection. + --number_of_connections; + if ( not kernel().node_manager.is_local_node_id( target_id ) ) + { + continue; + } + + Node* target_ptr = kernel().node_manager.get_node_or_proxy( target_id ); + const size_t target_thread = target_ptr->get_thread(); + + for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) + { + kernel().connection_manager.connect( source_id, + target_ptr, + target_thread, + synapse_model_[ indx ], + param_dicts_[ indx ][ target_thread ], + rng_delay_vec[ indx ], + rng_weight_vec[ indx ] ); + } + } + } +} + } // namespace nest #endif diff --git a/nestkernel/connection_creator_impl.h b/nestkernel/connection_creator_impl.h deleted file mode 100644 index e094ab59d5..0000000000 --- a/nestkernel/connection_creator_impl.h +++ /dev/null @@ -1,907 +0,0 @@ -/* - * connection_creator_impl.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 CONNECTION_CREATOR_IMPL_H -#define CONNECTION_CREATOR_IMPL_H - -#include "connection_creator.h" - -// C++ includes: -#include - -// Includes from nestkernel: -#include "kernel_manager.h" -#include "nest.h" - -namespace nest -{ -template < int D > -void -ConnectionCreator::connect( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - switch ( type_ ) - { - case Pairwise_bernoulli_on_source: - - pairwise_bernoulli_on_source_( source, source_nc, target, target_nc ); - break; - - case Fixed_indegree: - - fixed_indegree_( source, source_nc, target, target_nc ); - break; - - case Fixed_outdegree: - - fixed_outdegree_( source, source_nc, target, target_nc ); - break; - - case Pairwise_bernoulli_on_target: - - pairwise_bernoulli_on_target_( source, source_nc, target, target_nc ); - break; - - case Pairwise_poisson: - - pairwise_poisson_( source, source_nc, target, target_nc ); - break; - - default: - throw BadProperty( "Unknown connection type." ); - } -} - -template < typename Iterator, int D > -void -ConnectionCreator::connect_to_target_( Iterator from, - Iterator to, - Node* tgt_ptr, - const Position< D >& tgt_pos, - size_t tgt_thread, - const Layer< D >& source ) -{ - RngPtr rng = get_vp_specific_rng( tgt_thread ); - - // We create a source pos vector here that can be updated with the - // source position. This is done to avoid creating and destroying - // unnecessarily many vectors. - std::vector< double > source_pos( D ); - const std::vector< double > target_pos = tgt_pos.get_vector(); - - for ( Iterator iter = from; iter != to; ++iter ) - { - if ( not allow_autapses_ and ( iter->second == tgt_ptr->get_node_id() ) ) - { - continue; - } - iter->first.get_vector( source_pos ); - - if ( not kernel_ or rng->drand() < kernel_->value( rng, source_pos, target_pos, source, tgt_ptr ) ) - { - for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) - { - kernel().connection_manager.connect( iter->second, - tgt_ptr, - tgt_thread, - synapse_model_[ indx ], - param_dicts_[ indx ][ tgt_thread ], - delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), - weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); - } - } - } -} - -template < typename Iterator, int D > -void -ConnectionCreator::connect_to_target_poisson_( Iterator from, - Iterator to, - Node* tgt_ptr, - const Position< D >& tgt_pos, - size_t tgt_thread, - const Layer< D >& source ) -{ - RngPtr rng = get_vp_specific_rng( tgt_thread ); - - // We create a source pos vector here that can be updated with the - // source position. This is done to avoid creating and destroying - // unnecessarily many vectors. - std::vector< double > source_pos( D ); - const std::vector< double > target_pos = tgt_pos.get_vector(); - poisson_distribution poi_dist; - - for ( Iterator iter = from; iter != to; ++iter ) - { - if ( not allow_autapses_ and ( iter->second == tgt_ptr->get_node_id() ) ) - { - continue; - } - iter->first.get_vector( source_pos ); - - // Sample number of connections that are to be established - poisson_distribution::param_type param( kernel_->value( rng, source_pos, target_pos, source, tgt_ptr ) ); - const unsigned long num_conns = poi_dist( rng, param ); - for ( unsigned long conn_counter = 0; conn_counter < num_conns; ++conn_counter ) - { - for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) - { - kernel().connection_manager.connect( iter->second, - tgt_ptr, - tgt_thread, - synapse_model_[ indx ], - param_dicts_[ indx ][ tgt_thread ], - delay_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ), - weight_[ indx ]->value( rng, source_pos, target_pos, source, tgt_ptr ) ); - } - } - } -} - -template < int D > -ConnectionCreator::PoolWrapper_< D >::PoolWrapper_() - : masked_layer_( 0 ) - , positions_( 0 ) -{ -} - -template < int D > -ConnectionCreator::PoolWrapper_< D >::~PoolWrapper_< D >() -{ - if ( masked_layer_ ) - { - delete masked_layer_; - } -} - -template < int D > -void -ConnectionCreator::PoolWrapper_< D >::define( MaskedLayer< D >* ml ) -{ - assert( masked_layer_ == 0 ); - assert( positions_ == 0 ); - assert( ml != 0 ); - masked_layer_ = ml; -} - -template < int D > -void -ConnectionCreator::PoolWrapper_< D >::define( std::vector< std::pair< Position< D >, size_t > >* pos ) -{ - assert( masked_layer_ == 0 ); - assert( positions_ == 0 ); - assert( pos != 0 ); - positions_ = pos; -} - -template < int D > -typename Ntree< D, size_t >::masked_iterator -ConnectionCreator::PoolWrapper_< D >::masked_begin( const Position< D >& pos ) const -{ - return masked_layer_->begin( pos ); -} - -template < int D > -typename Ntree< D, size_t >::masked_iterator -ConnectionCreator::PoolWrapper_< D >::masked_end() const -{ - return masked_layer_->end(); -} - -template < int D > -typename std::vector< std::pair< Position< D >, size_t > >::iterator -ConnectionCreator::PoolWrapper_< D >::begin() const -{ - return positions_->begin(); -} - -template < int D > -typename std::vector< std::pair< Position< D >, size_t > >::iterator -ConnectionCreator::PoolWrapper_< D >::end() const -{ - return positions_->end(); -} - - -template < int D > -void -ConnectionCreator::pairwise_bernoulli_on_source_( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - // Connect using pairwise Bernoulli drawing source nodes (target driven) - // For each local target node: - // 1. Apply Mask to source layer - // 2. For each source node: Compute probability, draw random number, make - // connection conditionally - - // retrieve global positions, either for masked or unmasked pool - PoolWrapper_< D > pool; - if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor - { - pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, source_nc ) ); - } - else - { - pool.define( source.get_global_positions_vector( source_nc ) ); - } - - std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); - -#pragma omp parallel - { - const int thread_id = kernel().vp_manager.get_thread_id(); - try - { - 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 ) - { - Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); - - if ( not tgt->is_proxy() ) - { - const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); - - if ( mask_.get() ) - { - connect_to_target_( - pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, source ); - } - else - { - connect_to_target_( pool.begin(), pool.end(), tgt, target_pos, thread_id, source ); - } - } - } // for target_begin - } - catch ( std::exception& err ) - { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( thread_id ) = - std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); - } - } // omp parallel - // check if any exceptions have been raised - for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) - { - if ( exceptions_raised_.at( thr ).get() ) - { - throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); - } - } -} - - -template < int D > -void -ConnectionCreator::pairwise_bernoulli_on_target_( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - // Connecting using pairwise Bernoulli drawing target nodes (source driven) - // It is actually implemented as pairwise Bernoulli on source nodes, - // but with displacements computed in the target layer. The Mask has been - // reversed so that it can be applied to the source instead of the target. - // For each local target node: - // 1. Apply (Converse)Mask to source layer - // 2. For each source node: Compute probability, draw random number, make - // connection conditionally - - PoolWrapper_< D > pool; - if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor - { - // By supplying the target layer to the MaskedLayer constructor, the - // mask is mirrored so it may be applied to the source layer instead - pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, target, source_nc ) ); - } - else - { - pool.define( source.get_global_positions_vector( source_nc ) ); - } - - std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); - - // We only need to check the first in the NodeCollection - Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); - if ( not first_in_tgt->has_proxies() ) - { - throw IllegalConnection( "Spatial Connect with pairwise_bernoulli to devices is not possible." ); - } - -#pragma omp parallel - { - const int thread_id = kernel().vp_manager.get_thread_id(); - try - { - 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 ) - { - Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); - - assert( not tgt->is_proxy() ); - - const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); - - if ( mask_.get() ) - { - // We do the same as in the target driven case, except that we calculate displacements in the target layer. - // We therefore send in target as last parameter. - connect_to_target_( pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, target ); - } - else - { - // We do the same as in the target driven case, except that we calculate displacements in the target layer. - // We therefore send in target as last parameter. - connect_to_target_( pool.begin(), pool.end(), tgt, target_pos, thread_id, target ); - } - - } // end for - } - catch ( std::exception& err ) - { - // We must create a new exception here, err's lifetime ends at the end of the catch block. - exceptions_raised_.at( thread_id ) = - std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); - } - } // omp parallel - // check if any exceptions have been raised - for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) - { - if ( exceptions_raised_.at( thr ).get() ) - { - throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); - } - } -} - - -template < int D > -void -ConnectionCreator::pairwise_poisson_( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - // Connect using pairwise Poisson drawing source nodes (target driven) - // For each local target node: - // 1. Apply Mask to source layer - // 2. For each source node: Compute probability, draw random number, make - // connection conditionally - - // retrieve global positions, either for masked or unmasked pool - PoolWrapper_< D > pool; - if ( mask_.get() ) // MaskedLayer will be freed by PoolWrapper d'tor - { - pool.define( new MaskedLayer< D >( source, mask_, allow_oversized_, source_nc ) ); - } - else - { - pool.define( source.get_global_positions_vector( source_nc ) ); - } - - std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised_( kernel().vp_manager.get_num_threads() ); - -#pragma omp parallel - { - const int thread_id = kernel().vp_manager.get_thread_id(); - try - { - 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 ) - { - Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id, thread_id ); - - if ( not tgt->is_proxy() ) - { - const Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); - - if ( mask_.get() ) - { - connect_to_target_poisson_( - pool.masked_begin( target_pos ), pool.masked_end(), tgt, target_pos, thread_id, source ); - } - else - { - connect_to_target_poisson_( pool.begin(), pool.end(), tgt, target_pos, thread_id, source ); - } - } - } // for target_begin - } - catch ( std::exception& err ) - { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( thread_id ) = - std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); - } - } // omp parallel - // check if any exceptions have been raised - for ( size_t thr = 0; thr < kernel().vp_manager.get_num_threads(); ++thr ) - { - if ( exceptions_raised_.at( thr ).get() ) - { - throw WrappedThreadException( *( exceptions_raised_.at( thr ) ) ); - } - } -} - - -template < int D > -void -ConnectionCreator::fixed_indegree_( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - // fixed_indegree connections (fixed fan in) - // - // For each local target node: - // 1. Apply Mask to source layer - // 2. Compute connection probability for each source position - // 3. Draw source nodes and make connections - - // We only need to check the first in the NodeCollection - Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); - if ( not first_in_tgt->has_proxies() ) - { - throw IllegalConnection( "Spatial Connect with fixed_indegree to devices is not possible." ); - } - - NodeCollection::const_iterator target_begin = target_nc->rank_local_begin(); - NodeCollection::const_iterator target_end = target_nc->end(); - - // 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 ) - { - Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id ); - - assert( not tgt->is_proxy() ); - } - - if ( mask_.get() ) - { - MaskedLayer< D > masked_source( source, mask_, allow_oversized_, source_nc ); - const auto masked_source_end = masked_source.end(); - - std::vector< std::pair< Position< D >, size_t > > positions; - - 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 ); - - size_t target_thread = tgt->get_thread(); - RngPtr rng = get_vp_specific_rng( target_thread ); - Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); - - // We create a source pos vector here that can be updated with the - // source position. This is done to avoid creating and destroying - // unnecessarily many vectors. - std::vector< double > source_pos_vector( D ); - const std::vector< double > target_pos_vector = target_pos.get_vector(); - - unsigned long target_number_connections = - std::round( number_of_connections_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); - - // Get (position,node ID) pairs for sources inside mask - positions.resize( std::distance( masked_source.begin( target_pos ), masked_source_end ) ); - std::copy( masked_source.begin( target_pos ), masked_source_end, positions.begin() ); - - // We will select `number_of_connections_` sources within the mask. - // If there is no kernel, we can just draw uniform random numbers, - // but with a kernel we have to set up a probability distribution - // function using a discrete_distribution. - if ( kernel_ ) - { - - std::vector< double > probabilities; - probabilities.reserve( positions.size() ); - - // Collect probabilities for the sources - for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions.begin(); - iter != positions.end(); - ++iter ) - { - iter->first.get_vector( source_pos_vector ); - probabilities.push_back( kernel_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); - } - - if ( positions.empty() - or ( not allow_autapses_ and ( positions.size() == 1 ) and positions[ 0 ].second == target_id ) - or ( not allow_multapses_ and ( positions.size() < target_number_connections ) ) ) - { - std::string msg = String::compose( "Global target ID %1: Not enough sources found inside mask", target_id ); - throw KernelException( msg.c_str() ); - } - - // A discrete_distribution draws random integers with a non-uniform - // distribution. - discrete_distribution lottery; - const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); - lottery.param( param ); - - // If multapses are not allowed, we must keep track of which - // sources have been selected already. - std::vector< bool > is_selected( positions.size() ); - - // Draw `target_number_connections` sources - while ( target_number_connections > 0 ) - { - size_t random_id = lottery( rng ); - if ( not allow_multapses_ and is_selected[ random_id ] ) - { - continue; - } - - size_t source_id = positions[ random_id ].second; - if ( not allow_autapses_ and source_id == target_id ) - { - continue; - } - positions[ random_id ].first.get_vector( source_pos_vector ); - 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 ); - } - - is_selected[ random_id ] = true; - --target_number_connections; - } - } - else - { - - // no kernel - - if ( positions.empty() - or ( not allow_autapses_ and ( positions.size() == 1 ) and positions[ 0 ].second == target_id ) - or ( not allow_multapses_ and ( positions.size() < target_number_connections ) ) ) - { - std::string msg = String::compose( "Global target ID %1: Not enough sources found inside mask", target_id ); - throw KernelException( msg.c_str() ); - } - - // If multapses are not allowed, we must keep track of which - // sources have been selected already. - std::vector< bool > is_selected( positions.size() ); - - // Draw `target_number_connections` sources - while ( target_number_connections > 0 ) - { - const size_t random_id = rng->ulrand( positions.size() ); - if ( not allow_multapses_ and is_selected[ random_id ] ) - { - continue; - } - positions[ random_id ].first.get_vector( source_pos_vector ); - const size_t source_id = positions[ random_id ].second; - 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 ); - } - - is_selected[ random_id ] = true; - --target_number_connections; - } - } - } - } - else - { - // no mask - - // 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 ) - { - size_t target_id = ( *tgt_it ).node_id; - Node* const tgt = kernel().node_manager.get_node_or_proxy( target_id ); - size_t target_thread = tgt->get_thread(); - RngPtr rng = get_vp_specific_rng( target_thread ); - Position< D > target_pos = target.get_position( ( *tgt_it ).nc_index ); - - unsigned long target_number_connections = std::round( number_of_connections_->value( rng, tgt ) ); - - std::vector< double > source_pos_vector( D ); - const std::vector< double > target_pos_vector = target_pos.get_vector(); - - if ( ( positions->size() == 0 ) - or ( not allow_autapses_ and ( positions->size() == 1 ) and ( ( *positions )[ 0 ].second == target_id ) ) - or ( not allow_multapses_ and ( positions->size() < target_number_connections ) ) ) - { - std::string msg = String::compose( "Global target ID %1: Not enough sources found", target_id ); - throw KernelException( msg.c_str() ); - } - - // We will select `target_number_connections` sources within the mask. - // If there is no kernel, we can just draw uniform random numbers, - // but with a kernel we have to set up a probability distribution - // function using a discrete_distribution. - if ( kernel_ ) - { - - std::vector< double > probabilities; - probabilities.reserve( positions->size() ); - - // Collect probabilities for the sources - for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions->begin(); - iter != positions->end(); - ++iter ) - { - iter->first.get_vector( source_pos_vector ); - probabilities.push_back( kernel_->value( rng, source_pos_vector, target_pos_vector, source, tgt ) ); - } - - // A discrete_distribution draws random integers with a non-uniform - // distribution. - discrete_distribution lottery; - const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); - lottery.param( param ); - - // If multapses are not allowed, we must keep track of which - // sources have been selected already. - std::vector< bool > is_selected( positions->size() ); - - // Draw `target_number_connections` sources - while ( target_number_connections > 0 ) - { - const size_t random_id = lottery( rng ); - if ( not allow_multapses_ and is_selected[ random_id ] ) - { - continue; - } - - const size_t source_id = ( *positions )[ random_id ].second; - if ( not allow_autapses_ and source_id == target_id ) - { - continue; - } - - ( *positions )[ random_id ].first.get_vector( source_pos_vector ); - 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 ); - } - - is_selected[ random_id ] = true; - --target_number_connections; - } - } - else - { - - // no kernel - - // If multapses are not allowed, we must keep track of which - // sources have been selected already. - std::vector< bool > is_selected( positions->size() ); - - // Draw `target_number_connections` sources - while ( target_number_connections > 0 ) - { - const size_t random_id = rng->ulrand( positions->size() ); - if ( not allow_multapses_ and is_selected[ random_id ] ) - { - continue; - } - - const size_t source_id = ( *positions )[ random_id ].second; - if ( not allow_autapses_ and source_id == target_id ) - { - continue; - } - - ( *positions )[ random_id ].first.get_vector( source_pos_vector ); - 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 ); - } - - is_selected[ random_id ] = true; - --target_number_connections; - } - } - } - } -} - - -template < int D > -void -ConnectionCreator::fixed_outdegree_( Layer< D >& source, - NodeCollectionPTR source_nc, - Layer< D >& target, - NodeCollectionPTR target_nc ) -{ - // 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 - - // We only need to check the first in the NodeCollection - Node* const first_in_tgt = kernel().node_manager.get_node_or_proxy( target_nc->operator[]( 0 ) ); - if ( not first_in_tgt->has_proxies() ) - { - throw IllegalConnection( "Spatial Connect with fixed_outdegree to devices is not possible." ); - } - - 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 ) - { - Node* const tgt = kernel().node_manager.get_node_or_proxy( ( *tgt_it ).node_id ); - - assert( not tgt->is_proxy() ); - } - - // Fixed_outdegree connections (fixed fan out) - // - // For each (global) source: (All connections made on all mpi procs) - // 1. Apply mask to global targets - // 2. If using kernel: Compute connection probability for each global target - // 3. Draw connections to make using global rng - - MaskedLayer< D > masked_target( target, mask_, allow_oversized_, target_nc ); - const auto masked_target_end = masked_target.end(); - - // We create a target positions vector here that can be updated with the - // position and node ID pairs. This is done to avoid creating and destroying - // unnecessarily many vectors. - std::vector< std::pair< Position< D >, size_t > > target_pos_node_id_pairs; - std::vector< std::pair< Position< D >, size_t > > source_pos_node_id_pairs = - *source.get_global_positions_vector( source_nc ); - - for ( const auto& source_pos_node_id_pair : source_pos_node_id_pairs ) - { - const Position< D > source_pos = source_pos_node_id_pair.first; - const size_t source_id = source_pos_node_id_pair.second; - const auto src = kernel().node_manager.get_node_or_proxy( source_id ); - const std::vector< double > source_pos_vector = source_pos.get_vector(); - - // We create a target pos vector here that can be updated with the - // target position. This is done to avoid creating and destroying - // unnecessarily many vectors. - std::vector< double > target_pos_vector( D ); - std::vector< double > probabilities; - - // Find potential targets and probabilities - RngPtr grng = get_rank_synced_rng(); - target_pos_node_id_pairs.resize( std::distance( masked_target.begin( source_pos ), masked_target_end ) ); - std::copy( masked_target.begin( source_pos ), masked_target_end, target_pos_node_id_pairs.begin() ); - - probabilities.reserve( target_pos_node_id_pairs.size() ); - if ( kernel_ ) - { - for ( const auto& target_pos_node_id_pair : target_pos_node_id_pairs ) - { - // TODO: Why is probability calculated in source layer, but weight and delay in target layer? - target_pos_node_id_pair.first.get_vector( target_pos_vector ); - const auto tgt = kernel().node_manager.get_node_or_proxy( target_pos_node_id_pair.second ); - probabilities.push_back( kernel_->value( grng, source_pos_vector, target_pos_vector, source, tgt ) ); - } - } - else - { - probabilities.resize( target_pos_node_id_pairs.size(), 1.0 ); - } - - unsigned long number_of_connections = std::round( number_of_connections_->value( grng, src ) ); - - if ( target_pos_node_id_pairs.empty() - or ( not allow_multapses_ and target_pos_node_id_pairs.size() < number_of_connections ) ) - { - std::string msg = String::compose( "Global source ID %1: Not enough targets found", source_id ); - throw KernelException( msg.c_str() ); - } - - // Draw targets. A discrete_distribution draws random integers with a - // non-uniform distribution. - discrete_distribution lottery; - const discrete_distribution::param_type param( probabilities.begin(), probabilities.end() ); - lottery.param( param ); - - // If multapses are not allowed, we must keep track of which - // targets have been selected already. - std::vector< bool > is_selected( target_pos_node_id_pairs.size() ); - - // Draw `number_of_connections` targets - while ( number_of_connections > 0 ) - { - const size_t random_id = lottery( get_rank_synced_rng() ); - if ( not allow_multapses_ and is_selected[ random_id ] ) - { - continue; - } - const size_t target_id = target_pos_node_id_pairs[ random_id ].second; - if ( not allow_autapses_ and source_id == target_id ) - { - continue; - } - - is_selected[ random_id ] = true; - - target_pos_node_id_pairs[ random_id ].first.get_vector( target_pos_vector ); - - std::vector< double > rng_weight_vec; - std::vector< double > rng_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 ) ); - } - - // Each VP has now decided to create this connection and drawn any random parameter values - // required for it. Each VP thus counts the connection as created, but only the VP hosting the - // target neuron actually creates the connection. - --number_of_connections; - if ( not kernel().node_manager.is_local_node_id( target_id ) ) - { - continue; - } - - Node* target_ptr = kernel().node_manager.get_node_or_proxy( target_id ); - const size_t target_thread = target_ptr->get_thread(); - - for ( size_t indx = 0; indx < synapse_model_.size(); ++indx ) - { - kernel().connection_manager.connect( source_id, - target_ptr, - target_thread, - synapse_model_[ indx ], - param_dicts_[ indx ][ target_thread ], - rng_delay_vec[ indx ], - rng_weight_vec[ indx ] ); - } - } - } -} - -} // namespace nest - -#endif diff --git a/nestkernel/connection_label.h b/nestkernel/connection_label.h index a20b55f850..860f6994e2 100644 --- a/nestkernel/connection_label.h +++ b/nestkernel/connection_label.h @@ -25,7 +25,7 @@ #include "dictdatum.h" #include "dictutils.h" -#include "nest.h" +#include "exceptions.h" #include "nest_names.h" namespace nest diff --git a/nestkernel/connection_manager.cpp b/nestkernel/connection_manager.cpp index 0924fb73e2..c6e4cf954e 100644 --- a/nestkernel/connection_manager.cpp +++ b/nestkernel/connection_manager.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,6 @@ #include "conn_builder_conngen.h" #include "conn_builder_factory.h" #include "connection_label.h" -#include "connection_manager_impl.h" #include "connector_base.h" #include "connector_model.h" #include "delay_checker.h" @@ -53,13 +53,14 @@ #include "eprop_archiving_node_recurrent.h" #include "exceptions.h" #include "kernel_manager.h" -#include "mpi_manager_impl.h" +#include "logging_manager.h" +#include "model_manager.h" #include "nest_names.h" #include "node.h" +#include "node_manager.h" +#include "simulation_manager.h" #include "sonata_connector.h" -#include "stopwatch_impl.h" -#include "target_table_devices_impl.h" -#include "vp_manager_impl.h" +#include "sp_manager.h" // Includes from sli: #include "dictutils.h" @@ -67,8 +68,10 @@ #include "token.h" #include "tokenutils.h" +namespace nest +{ -nest::ConnectionManager::ConnectionManager() +ConnectionManager::ConnectionManager() : connruledict_( new Dictionary() ) , connbuilder_factories_() , thirdconnruledict_( new Dictionary() ) @@ -87,7 +90,7 @@ nest::ConnectionManager::ConnectionManager() { } -nest::ConnectionManager::~ConnectionManager() +ConnectionManager::~ConnectionManager() { // Memory leak on purpose! // The ConnectionManager is deleted, when the network is deleted, and @@ -98,7 +101,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 ) { @@ -158,7 +161,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(); @@ -187,7 +190,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 +214,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() ); @@ -240,7 +243,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 +288,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 +338,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 +349,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 +363,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 +378,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 +391,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, @@ -408,8 +411,8 @@ nest::ConnectionManager::get_conn_builder( const std::string& name, return cb; } -nest::ThirdOutBuilder* -nest::ConnectionManager::get_third_conn_builder( const std::string& name, +ThirdOutBuilder* +ConnectionManager::get_third_conn_builder( const std::string& name, NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdInBuilder* third_in, @@ -429,7 +432,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 +441,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 +490,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 +516,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() ) { @@ -560,7 +563,7 @@ 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, @@ -592,7 +595,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,7 +636,7 @@ 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, @@ -808,7 +811,7 @@ nest::ConnectionManager::connect_arrays( long* sources, } void -nest::ConnectionManager::connect_sonata( const DictionaryDatum& graph_specs, const long hyberslab_size ) +ConnectionManager::connect_sonata( const DictionaryDatum& graph_specs, const long hyberslab_size ) { #ifdef HAVE_HDF5 SonataConnector sonata_connector( graph_specs, hyberslab_size ); @@ -823,7 +826,7 @@ nest::ConnectionManager::connect_sonata( const DictionaryDatum& graph_specs, con } void -nest::ConnectionManager::connect_tripartite( NodeCollectionPTR sources, +ConnectionManager::connect_tripartite( NodeCollectionPTR sources, NodeCollectionPTR targets, NodeCollectionPTR third, const DictionaryDatum& conn_spec, @@ -884,7 +887,7 @@ nest::ConnectionManager::connect_tripartite( NodeCollectionPTR sources, void -nest::ConnectionManager::connect_( Node& source, +ConnectionManager::connect_( Node& source, Node& target, const size_t s_node_id, const size_t tid, @@ -940,7 +943,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 +959,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 +974,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 +992,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 +1017,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 +1036,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 +1054,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 +1068,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 +1083,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 +1098,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 +1180,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 +1193,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 +1218,7 @@ nest::ConnectionManager::split_to_neuron_device_vectors_( const size_t tid, } void -nest::ConnectionManager::get_connections_( const size_t tid, +ConnectionManager::get_connections_( const size_t tid, std::deque< ConnectionID >& conns_in_thread, NodeCollectionPTR, NodeCollectionPTR, @@ -1397,7 +1397,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 ) @@ -1411,7 +1411,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 ) { @@ -1431,7 +1431,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 ) @@ -1473,7 +1473,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 @@ -1499,7 +1499,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 { @@ -1531,7 +1531,7 @@ nest::ConnectionManager::compute_compressed_secondary_recv_buffer_positions( con { const size_t source_node_id = source_table_.get_node_id( tid, syn_id, lcid ); const size_t sg_s_id = source_table_.pack_source_node_id_and_syn_id( source_node_id, syn_id ); - const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( source_node_id ); + const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( source_node_id ); positions[ lcid ] = buffer_pos_of_source_node_id_syn_id_[ sg_s_id ] + kernel().mpi_manager.get_recv_displacement_secondary_events_in_int( source_rank ); @@ -1541,8 +1541,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. @@ -1634,7 +1634,7 @@ 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() ) ) { @@ -1663,7 +1663,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 ) { @@ -1711,13 +1711,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 ]; @@ -1741,7 +1741,7 @@ nest::ConnectionManager::remove_disabled_connections( const size_t tid ) } void -nest::ConnectionManager::resize_connections() +ConnectionManager::resize_connections() { kernel().vp_manager.assert_thread_parallel(); @@ -1752,19 +1752,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 ); @@ -1781,14 +1781,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_ ) { @@ -1799,9 +1799,9 @@ nest::ConnectionManager::collect_compressed_spike_data( const size_t tid ) } // of omp single; implicit barrier source_table_.collect_compressible_sources( tid ); - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); #pragma omp single { source_table_.fill_compressed_spike_data( compressed_spike_data_ ); @@ -1810,7 +1810,7 @@ nest::ConnectionManager::collect_compressed_spike_data( const size_t tid ) } bool -nest::ConnectionManager::fill_target_buffer( const size_t tid, +ConnectionManager::fill_target_buffer( const size_t tid, const size_t rank_start, const size_t rank_end, std::vector< TargetData >& send_buffer_target_data, @@ -1836,7 +1836,7 @@ nest::ConnectionManager::fill_target_buffer( const size_t tid, while ( source_2_idx != csd_maps.at( syn_id ).end() ) { const auto source_gid = source_2_idx->first; - const auto source_rank = kernel().mpi_manager.get_process_id_of_node_id( source_gid ); + const auto source_rank = kernel().vp_manager.get_process_id_of_node_id( source_gid ); if ( not( rank_start <= source_rank and source_rank < rank_end ) ) { // We are not responsible for this source. @@ -1925,7 +1925,7 @@ nest::ConnectionManager::fill_target_buffer( const size_t tid, } void -nest::ConnectionManager::initialize_iteration_state() +ConnectionManager::initialize_iteration_state() { const size_t num_threads = kernel().vp_manager.get_num_threads(); iteration_state_.clear(); @@ -1940,3 +1940,23 @@ nest::ConnectionManager::initialize_iteration_state() iteration_state_.push_back( std::pair< size_t, std::map< size_t, CSDMapEntry >::const_iterator >( 0, begin ) ); } } + +void +ConnectionManager::send_to_devices( const size_t tid, const size_t source_node_id, Event& e ) +{ + target_table_devices_.send_to_device( tid, source_node_id, e, kernel().model_manager.get_connection_models( tid ) ); +} + +void +ConnectionManager::send_to_devices( const size_t tid, const size_t source_node_id, SecondaryEvent& e ) +{ + target_table_devices_.send_to_device( tid, source_node_id, e, kernel().model_manager.get_connection_models( tid ) ); +} + +void +ConnectionManager::send_from_device( const size_t tid, const size_t ldid, Event& e ) +{ + target_table_devices_.send_from_device( tid, ldid, e, kernel().model_manager.get_connection_models( tid ) ); +} + +} diff --git a/nestkernel/connection_manager.h b/nestkernel/connection_manager.h index ca0c07d11d..d9c032f56c 100644 --- a/nestkernel/connection_manager.h +++ b/nestkernel/connection_manager.h @@ -31,11 +31,10 @@ #include "stopwatch.h" // Includes from nestkernel: -#include "conn_builder.h" +#include "conn_builder_factory.h" #include "connection_id.h" #include "connector_base.h" #include "nest_time.h" -#include "nest_timeconverter.h" #include "nest_types.h" #include "node_collection.h" #include "per_thread_bool_indicator.h" @@ -54,13 +53,17 @@ namespace nest { class GenericBipartiteConnBuilderFactory; class GenericThirdConnBuilderFactory; -class spikecounter; class Node; class Event; class SecondaryEvent; class DelayChecker; class GrowthCurve; class SpikeData; +class BipartiteConnBuilder; +class ThirdOutBuilder; +class ThirdInBuilder; +class Time; +class TimeConverter; class ConnectionManager : public ManagerInterface { @@ -75,18 +78,25 @@ class ConnectionManager : public ManagerInterface }; ConnectionManager(); + ~ConnectionManager() override; void initialize( const bool ) override; + void finalize( const bool ) override; + void set_status( const DictionaryDatum& ) override; + void get_status( DictionaryDatum& ) override; bool valid_connection_rule( std::string ); void compute_target_data_buffer_size(); + void compute_compressed_secondary_recv_buffer_positions( const size_t tid ); + void collect_compressed_spike_data( const size_t tid ); + void clear_compressed_spike_data_map(); /** @@ -278,6 +288,7 @@ class ConnectionManager : public ManagerInterface size_t get_target_node_id( const size_t tid, const synindex syn_id, const size_t lcid ) const; bool get_device_connected( size_t tid, size_t lcid ) const; + /** * Triggered by volume transmitter in update. * @@ -311,6 +322,7 @@ class ConnectionManager : public ManagerInterface * Send event e to all device targets of source source_node_id */ void send_to_devices( const size_t tid, const size_t source_node_id, Event& e ); + void send_to_devices( const size_t tid, const size_t source_node_id, SecondaryEvent& e ); /** @@ -480,12 +492,14 @@ class ConnectionManager : public ManagerInterface NodeCollectionPTR target, synindex syn_id, long synapse_label ) const; + void get_connections_to_targets_( const size_t tid, std::deque< ConnectionID >& connectome, NodeCollectionPTR source, NodeCollectionPTR target, synindex syn_id, long synapse_label ) const; + void get_connections_from_sources_( const size_t tid, std::deque< ConnectionID >& connectome, NodeCollectionPTR source, @@ -946,6 +960,30 @@ ConnectionManager::clear_compressed_spike_data_map() source_table_.clear_compressed_spike_data_map(); } +template < typename ConnBuilder > +void +ConnectionManager::register_conn_builder( const std::string& name ) +{ + assert( not connruledict_->known( name ) ); + GenericBipartiteConnBuilderFactory* cb = new BipartiteConnBuilderFactory< ConnBuilder >(); + assert( cb ); + const int id = connbuilder_factories_.size(); + connbuilder_factories_.push_back( cb ); + connruledict_->insert( name, id ); +} + +template < typename ThirdConnBuilder > +void +ConnectionManager::register_third_conn_builder( const std::string& name ) +{ + assert( not thirdconnruledict_->known( name ) ); + GenericThirdConnBuilderFactory* cb = new ThirdConnBuilderFactory< ThirdConnBuilder >(); + assert( cb ); + const int id = thirdconnbuilder_factories_.size(); + thirdconnbuilder_factories_.push_back( cb ); + thirdconnruledict_->insert( name, id ); +} + } // namespace nest #endif /* CONNECTION_MANAGER_H */ diff --git a/nestkernel/connection_manager_impl.h b/nestkernel/connection_manager_impl.h deleted file mode 100644 index 3c8d74034c..0000000000 --- a/nestkernel/connection_manager_impl.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * connection_manager_impl.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 CONNECTION_MANAGER_IMPL_H -#define CONNECTION_MANAGER_IMPL_H - -#include "connection_manager.h" - -// C++ includes: -#include - -// Includes from nestkernel: -#include "conn_builder.h" -#include "conn_builder_factory.h" -#include "connector_base.h" -#include "kernel_manager.h" -#include "target_table_devices_impl.h" - -namespace nest -{ - -template < typename ConnBuilder > -void -ConnectionManager::register_conn_builder( const std::string& name ) -{ - assert( not connruledict_->known( name ) ); - GenericBipartiteConnBuilderFactory* cb = new BipartiteConnBuilderFactory< ConnBuilder >(); - assert( cb ); - const int id = connbuilder_factories_.size(); - connbuilder_factories_.push_back( cb ); - connruledict_->insert( name, id ); -} - -template < typename ThirdConnBuilder > -void -ConnectionManager::register_third_conn_builder( const std::string& name ) -{ - assert( not thirdconnruledict_->known( name ) ); - GenericThirdConnBuilderFactory* cb = new ThirdConnBuilderFactory< ThirdConnBuilder >(); - assert( cb ); - const int id = thirdconnbuilder_factories_.size(); - thirdconnbuilder_factories_.push_back( cb ); - thirdconnruledict_->insert( name, id ); -} - -inline void -ConnectionManager::send_to_devices( const size_t tid, const size_t source_node_id, Event& e ) -{ - target_table_devices_.send_to_device( tid, source_node_id, e, kernel().model_manager.get_connection_models( tid ) ); -} - -inline void -ConnectionManager::send_to_devices( const size_t tid, const size_t source_node_id, SecondaryEvent& e ) -{ - target_table_devices_.send_to_device( tid, source_node_id, e, kernel().model_manager.get_connection_models( tid ) ); -} - -inline void -ConnectionManager::send_from_device( const size_t tid, const size_t ldid, Event& e ) -{ - target_table_devices_.send_from_device( tid, ldid, e, kernel().model_manager.get_connection_models( tid ) ); -} - -} // namespace nest - -#endif /* CONNECTION_MANAGER_IMPL_H */ diff --git a/nestkernel/connector_base.cpp b/nestkernel/connector_base.cpp new file mode 100644 index 0000000000..951e3c0334 --- /dev/null +++ b/nestkernel/connector_base.cpp @@ -0,0 +1,50 @@ +/* + * connector_base.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 "connector_base.h" + +#include "connection_manager.h" + +namespace nest +{ + +void +ConnectorBase::prepare_weight_recorder_event( WeightRecorderEvent& wr_e, + const size_t tid, + const synindex syn_id, + const unsigned int lcid, + const Event& e, + const CommonSynapseProperties& cp ) +{ + wr_e.set_port( e.get_port() ); + wr_e.set_rport( e.get_rport() ); + wr_e.set_stamp( e.get_stamp() ); + // Sender is not available for SecondaryEvents, and not needed, so we do not set it to avoid undefined behavior. + wr_e.set_sender_node_id( kernel().connection_manager.get_source_node_id( tid, syn_id, lcid ) ); + wr_e.set_weight( e.get_weight() ); + wr_e.set_delay_steps( e.get_delay_steps() ); + wr_e.set_receiver( *static_cast< Node* >( cp.get_weight_recorder() ) ); + // Set the node_id of the postsynaptic node as receiver node ID + wr_e.set_receiver_node_id( e.get_receiver_node_id() ); +} + +} // namespace nest diff --git a/nestkernel/connector_base.h b/nestkernel/connector_base.h index 7cdd91b1e8..55bf7398f3 100644 --- a/nestkernel/connector_base.h +++ b/nestkernel/connector_base.h @@ -28,12 +28,18 @@ // C++ includes: #include +#include #include +// Includes from models: +#include "weight_recorder.h" + +#ifdef HAVE_SIONLIB +#include +#endif + // Includes from libnestutil: -#include "compose.hpp" #include "sort.h" -#include "vector_util.h" // Includes from nestkernel: #include "common_synapse_properties.h" @@ -47,12 +53,15 @@ #include "spikecounter.h" // Includes from sli: -#include "arraydatum.h" #include "dictutils.h" namespace nest { +class ConnectorModel; +template < typename ConnectionT > +class GenericConnectorModel; + /** * Base class to allow storing Connectors for different synapse types * in vectors. We define the interface here to avoid casting. @@ -63,7 +72,6 @@ namespace nest */ class ConnectorBase { - public: // Destructor needs to be declared virtual to avoid undefined // behavior, avoid possible memory leak and needs to be defined to @@ -211,6 +219,14 @@ class ConnectorBase * Remove disabled connections from the connector. */ virtual void remove_disabled_connections( const size_t first_disabled_index ) = 0; + +protected: + void prepare_weight_recorder_event( WeightRecorderEvent& wr_e, + const size_t tid, + const synindex syn_id, + const unsigned int lcid, + const Event& e, + const CommonSynapseProperties& cp ); }; /** @@ -219,7 +235,6 @@ class ConnectorBase template < typename ConnectionT > class Connector : public ConnectorBase { -private: BlockVector< ConnectionT > C_; const synindex syn_id_; @@ -425,7 +440,6 @@ class Connector : public ConnectorBase return 1 + lcid_offset; // event was delivered to at least one target } - // Implemented in connector_base_impl.h void send_weight_event( const size_t tid, const unsigned int lcid, Event& e, const CommonSynapseProperties& cp ) override; @@ -514,6 +528,24 @@ class Connector : public ConnectorBase } }; +template < typename ConnectionT > +void +Connector< ConnectionT >::send_weight_event( const size_t tid, + const unsigned int lcid, + Event& e, + const CommonSynapseProperties& cp ) +{ + // If the pointer to the receiver node in the event is invalid, + // the event was not sent, and a WeightRecorderEvent is therefore not created. + if ( cp.get_weight_recorder() and e.receiver_is_valid() ) + { + // Create new event to record the weight and copy relevant content. + WeightRecorderEvent wr_e; + prepare_weight_recorder_event( wr_e, tid, syn_id_, lcid, e, cp ); + wr_e(); + } +} + } // of namespace nest #endif diff --git a/nestkernel/connector_base_impl.h b/nestkernel/connector_base_impl.h index a322b2e336..e69de29bb2 100644 --- a/nestkernel/connector_base_impl.h +++ b/nestkernel/connector_base_impl.h @@ -1,67 +0,0 @@ -/* - * connector_base_impl.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 . - * - */ - -#include "connector_base.h" - -// Includes from nestkernel: -#include "kernel_manager.h" - -// Includes from models: -#include "weight_recorder.h" - -#ifndef CONNECTOR_BASE_IMPL_H -#define CONNECTOR_BASE_IMPL_H - -namespace nest -{ - -template < typename ConnectionT > -void -Connector< ConnectionT >::send_weight_event( const size_t tid, - const unsigned int lcid, - Event& e, - const CommonSynapseProperties& cp ) -{ - // If the pointer to the receiver node in the event is invalid, - // the event was not sent, and a WeightRecorderEvent is therefore not created. - if ( cp.get_weight_recorder() and e.receiver_is_valid() ) - { - // Create new event to record the weight and copy relevant content. - WeightRecorderEvent wr_e; - wr_e.set_port( e.get_port() ); - wr_e.set_rport( e.get_rport() ); - wr_e.set_stamp( e.get_stamp() ); - // Sender is not available for SecondaryEvents, and not needed, so we do not - // set it to avoid undefined behavior. - wr_e.set_sender_node_id( kernel().connection_manager.get_source_node_id( tid, syn_id_, lcid ) ); - wr_e.set_weight( e.get_weight() ); - wr_e.set_delay_steps( e.get_delay_steps() ); - wr_e.set_receiver( *static_cast< Node* >( cp.get_weight_recorder() ) ); - // Set the node_id of the postsynaptic node as receiver node ID - wr_e.set_receiver_node_id( e.get_receiver_node_id() ); - wr_e(); - } -} - -} // of namespace nest - -#endif diff --git a/nestkernel/connector_model.cpp b/nestkernel/connector_model.cpp index 6e3bb9f078..a200aafd8c 100644 --- a/nestkernel/connector_model.cpp +++ b/nestkernel/connector_model.cpp @@ -21,6 +21,7 @@ */ #include "connector_model.h" +#include "model_manager.h" namespace nest { @@ -39,4 +40,10 @@ ConnectorModel::ConnectorModel( const ConnectorModel& cm, const std::string name { } +size_t +ConnectorModel::get_synapse_model_id( const std::string& name ) +{ + return kernel().model_manager.get_synapse_model_id( name ); +} + } // namespace nest diff --git a/nestkernel/connector_model.h b/nestkernel/connector_model.h index 0a7f83ce8e..5cd64a9d16 100644 --- a/nestkernel/connector_model.h +++ b/nestkernel/connector_model.h @@ -28,17 +28,16 @@ #include // Includes from libnestutil: +#include "enum_bitfield.h" #include "numerics.h" // Includes from nestkernel: -#include "enum_bitfield.h" #include "event.h" #include "nest_time.h" #include "nest_types.h" #include "secondary_event.h" +#include "simulation_manager.h" -// Includes from sli: -#include "dictutils.h" namespace nest { @@ -143,6 +142,9 @@ class ConnectorModel } protected: + // helper function to avoid circular dependency + static size_t get_synapse_model_id( const std::string& name ); + std::string name_; //!< name of the ConnectorModel bool default_delay_needs_check_; //!< indicates whether the default delay must be checked ConnectionModelProperties properties_; //!< connection properties diff --git a/nestkernel/connector_model_impl.h b/nestkernel/connector_model_impl.h index fc831cb916..4527a8dfac 100644 --- a/nestkernel/connector_model_impl.h +++ b/nestkernel/connector_model_impl.h @@ -20,28 +20,9 @@ * */ -#ifndef CONNECTOR_MODEL_IMPL_H -#define CONNECTOR_MODEL_IMPL_H - -#include "connector_model.h" - -// Generated includes: -#include "config.h" - -// Includes from libnestutil: -#include "compose.hpp" -#include "enum_bitfield.h" - -// Includes from nestkernel: #include "connector_base.h" +#include "connector_model.h" #include "delay_checker.h" -#include "kernel_manager.h" -#include "nest_time.h" -#include "nest_timeconverter.h" -#include "secondary_event_impl.h" - -// Includes from sli: -#include "dictutils.h" namespace nest { @@ -63,7 +44,7 @@ namespace nest // } template < typename ConnectionT > -ConnectorModel* +inline ConnectorModel* GenericConnectorModel< ConnectionT >::clone( std::string name, synindex syn_id ) const { ConnectorModel* new_cm = new GenericConnectorModel( *this, name ); // calls copy construtor @@ -79,7 +60,7 @@ GenericConnectorModel< ConnectionT >::clone( std::string name, synindex syn_id ) } template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::calibrate( const TimeConverter& tc ) { // calibrate the delay of the default properties here @@ -93,7 +74,7 @@ GenericConnectorModel< ConnectionT >::calibrate( const TimeConverter& tc ) } template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::get_status( DictionaryDatum& d ) const { // first get properties common to all synapses @@ -105,7 +86,7 @@ GenericConnectorModel< ConnectionT >::get_status( DictionaryDatum& d ) const ( *d )[ names::receptor_type ] = receptor_type_; ( *d )[ names::synapse_model ] = LiteralDatum( name_ ); - ( *d )[ names::synapse_modelid ] = kernel().model_manager.get_synapse_model_id( name_ ); + ( *d )[ names::synapse_modelid ] = get_synapse_model_id( name_ ); ( *d )[ names::requires_symmetric ] = has_property( ConnectionModelProperties::REQUIRES_SYMMETRIC ); ( *d )[ names::has_delay ] = has_property( ConnectionModelProperties::HAS_DELAY ); } @@ -139,7 +120,7 @@ GenericConnectorModel< ConnectionT >::set_status( const DictionaryDatum& d ) } template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::check_synapse_params( const DictionaryDatum& syn_spec ) const { // This is called just once per Connect() call, so we need not worry much about performance. @@ -161,7 +142,7 @@ GenericConnectorModel< ConnectionT >::check_synapse_params( const DictionaryDatu template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::used_default_delay() { // if not used before, check now. Solves bug #138, MH 08-01-08 @@ -204,21 +185,21 @@ GenericConnectorModel< ConnectionT >::used_default_delay() } template < typename ConnectionT > -size_t +inline size_t GenericConnectorModel< ConnectionT >::get_syn_id() const { return default_connection_.get_syn_id(); } template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::set_syn_id( synindex syn_id ) { default_connection_.set_syn_id( syn_id ); } template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::add_connection( Node& src, Node& tgt, std::vector< ConnectorBase* >& thread_local_connectors, @@ -294,7 +275,7 @@ GenericConnectorModel< ConnectionT >::add_connection( Node& src, template < typename ConnectionT > -void +inline void GenericConnectorModel< ConnectionT >::add_connection_( Node& src, Node& tgt, std::vector< ConnectorBase* >& thread_local_connectors, @@ -322,5 +303,3 @@ GenericConnectorModel< ConnectionT >::add_connection_( Node& src, } } // namespace nest - -#endif diff --git a/nestkernel/delay_checker.cpp b/nestkernel/delay_checker.cpp index 8a1776c98e..7148ebd110 100644 --- a/nestkernel/delay_checker.cpp +++ b/nestkernel/delay_checker.cpp @@ -30,6 +30,13 @@ #include "kernel_manager.h" #include "nest_timeconverter.h" +#include "compose.hpp" +#include "connection_manager.h" +#include "dictutils.h" +#include "logging.h" +#include "logging_manager.h" +#include "nest_names.h" + nest::DelayChecker::DelayChecker() : min_delay_( Time::pos_inf() ) , max_delay_( Time::neg_inf() ) diff --git a/nestkernel/eprop_archiving_node.h b/nestkernel/eprop_archiving_node.h index 04cfc2d3ba..673f14814c 100644 --- a/nestkernel/eprop_archiving_node.h +++ b/nestkernel/eprop_archiving_node.h @@ -152,6 +152,161 @@ class EpropArchivingNode : public Node const long delay_out_rec_ = 1; }; +template < typename HistEntryT > +EpropArchivingNode< HistEntryT >::EpropArchivingNode() + : Node() + , eprop_indegree_( 0 ) +{ +} + +template < typename HistEntryT > +EpropArchivingNode< HistEntryT >::EpropArchivingNode( const EpropArchivingNode& n ) + : Node( n ) + , eprop_indegree_( n.eprop_indegree_ ) +{ +} + +template < typename HistEntryT > +void +EpropArchivingNode< HistEntryT >::register_eprop_connection() +{ + ++eprop_indegree_; + + const long t_first_entry = model_dependent_history_shift_(); + + const auto it_hist = get_update_history( t_first_entry ); + + if ( it_hist == update_history_.end() or it_hist->t_ != t_first_entry ) + { + update_history_.insert( it_hist, HistEntryEpropUpdate( t_first_entry, 1 ) ); + } + else + { + ++it_hist->access_counter_; + } +} + +template < typename HistEntryT > +void +EpropArchivingNode< HistEntryT >::write_update_to_history( const long t_previous_update, + const long t_current_update, + const long eprop_isi_trace_cutoff ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + const long shift = model_dependent_history_shift_(); + + const auto it_hist_curr = get_update_history( t_current_update + shift ); + + if ( it_hist_curr != update_history_.end() and it_hist_curr->t_ == t_current_update + shift ) + { + ++it_hist_curr->access_counter_; + } + else + { + update_history_.insert( it_hist_curr, HistEntryEpropUpdate( t_current_update + shift, 1 ) ); + + if ( not history_shift_required_() ) + { + erase_used_eprop_history( eprop_isi_trace_cutoff ); + } + } + + const auto it_hist_prev = get_update_history( t_previous_update + shift ); + + if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_previous_update + shift ) + { + // If an entry exists for the previous update time, decrement its access counter + --it_hist_prev->access_counter_; + if ( it_hist_prev->access_counter_ == 0 ) + { + update_history_.erase( it_hist_prev ); + } + } +} + +template < typename HistEntryT > +std::vector< HistEntryEpropUpdate >::iterator +EpropArchivingNode< HistEntryT >::get_update_history( const long time_step ) +{ + return std::lower_bound( update_history_.begin(), update_history_.end(), time_step ); +} + +template < typename HistEntryT > +typename std::vector< HistEntryT >::iterator +EpropArchivingNode< HistEntryT >::get_eprop_history( const long time_step ) +{ + return std::lower_bound( eprop_history_.begin(), eprop_history_.end(), time_step ); +} + +template < typename HistEntryT > +void +EpropArchivingNode< HistEntryT >::erase_used_eprop_history() +{ + if ( eprop_history_.empty() // nothing to remove + or update_history_.empty() // no time markers to check + ) + { + return; + } + + const long update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps(); + + auto it_update_hist = update_history_.begin(); + + for ( long t = update_history_.begin()->t_; + t <= ( update_history_.end() - 1 )->t_ and it_update_hist != update_history_.end(); + t += update_interval ) + { + if ( it_update_hist->t_ == t ) + { + ++it_update_hist; + } + else + { + // erase no longer needed entries for update intervals with no spikes sent to the target neuron + eprop_history_.erase( get_eprop_history( t ), get_eprop_history( t + update_interval ) ); + } + } + // erase no longer needed entries before the earliest current update + eprop_history_.erase( get_eprop_history( 0 ), get_eprop_history( update_history_.begin()->t_ ) ); +} + +template < typename HistEntryT > +void +EpropArchivingNode< HistEntryT >::erase_used_eprop_history( const long eprop_isi_trace_cutoff ) +{ + if ( eprop_history_.empty() // nothing to remove + or update_history_.size() < 2 // no time markers to check + ) + { + return; + } + + const long t_prev = ( update_history_.end() - 2 )->t_; + const long t_curr = ( update_history_.end() - 1 )->t_; + + if ( t_prev + eprop_isi_trace_cutoff < t_curr ) + { + // erase no longer needed entries to be ignored by trace cutoff + eprop_history_.erase( get_eprop_history( t_prev + eprop_isi_trace_cutoff ), get_eprop_history( t_curr ) ); + } + + // erase no longer needed entries before the earliest current update + eprop_history_.erase( + get_eprop_history( std::numeric_limits< long >::min() ), get_eprop_history( update_history_.begin()->t_ - 1 ) ); +} + +template < typename HistEntryT > +inline double +EpropArchivingNode< HistEntryT >::get_eprop_history_duration() const +{ + return Time::get_resolution().get_ms() * eprop_history_.size(); +} + } // namespace nest #endif // EPROP_ARCHIVING_NODE_H diff --git a/nestkernel/eprop_archiving_node_impl.h b/nestkernel/eprop_archiving_node_impl.h deleted file mode 100644 index 7c4c60a52e..0000000000 --- a/nestkernel/eprop_archiving_node_impl.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * eprop_archiving_node_impl.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 EPROP_ARCHIVING_NODE_IMPL_H -#define EPROP_ARCHIVING_NODE_IMPL_H - -#include "eprop_archiving_node.h" - -// Includes from nestkernel: -#include "kernel_manager.h" - -// Includes from sli: -#include "dictutils.h" - -namespace nest -{ - -template < typename HistEntryT > -EpropArchivingNode< HistEntryT >::EpropArchivingNode() - : Node() - , eprop_indegree_( 0 ) -{ -} - -template < typename HistEntryT > -EpropArchivingNode< HistEntryT >::EpropArchivingNode( const EpropArchivingNode& n ) - : Node( n ) - , eprop_indegree_( n.eprop_indegree_ ) -{ -} - -template < typename HistEntryT > -void -EpropArchivingNode< HistEntryT >::register_eprop_connection() -{ - ++eprop_indegree_; - - const long t_first_entry = model_dependent_history_shift_(); - - const auto it_hist = get_update_history( t_first_entry ); - - if ( it_hist == update_history_.end() or it_hist->t_ != t_first_entry ) - { - update_history_.insert( it_hist, HistEntryEpropUpdate( t_first_entry, 1 ) ); - } - else - { - ++it_hist->access_counter_; - } -} - -template < typename HistEntryT > -void -EpropArchivingNode< HistEntryT >::write_update_to_history( const long t_previous_update, - const long t_current_update, - const long eprop_isi_trace_cutoff ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - const long shift = model_dependent_history_shift_(); - - const auto it_hist_curr = get_update_history( t_current_update + shift ); - - if ( it_hist_curr != update_history_.end() and it_hist_curr->t_ == t_current_update + shift ) - { - ++it_hist_curr->access_counter_; - } - else - { - update_history_.insert( it_hist_curr, HistEntryEpropUpdate( t_current_update + shift, 1 ) ); - - if ( not history_shift_required_() ) - { - erase_used_eprop_history( eprop_isi_trace_cutoff ); - } - } - - const auto it_hist_prev = get_update_history( t_previous_update + shift ); - - if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_previous_update + shift ) - { - // If an entry exists for the previous update time, decrement its access counter - --it_hist_prev->access_counter_; - if ( it_hist_prev->access_counter_ == 0 ) - { - update_history_.erase( it_hist_prev ); - } - } -} - -template < typename HistEntryT > -std::vector< HistEntryEpropUpdate >::iterator -EpropArchivingNode< HistEntryT >::get_update_history( const long time_step ) -{ - return std::lower_bound( update_history_.begin(), update_history_.end(), time_step ); -} - -template < typename HistEntryT > -typename std::vector< HistEntryT >::iterator -EpropArchivingNode< HistEntryT >::get_eprop_history( const long time_step ) -{ - return std::lower_bound( eprop_history_.begin(), eprop_history_.end(), time_step ); -} - -template < typename HistEntryT > -void -EpropArchivingNode< HistEntryT >::erase_used_eprop_history() -{ - if ( eprop_history_.empty() // nothing to remove - or update_history_.empty() // no time markers to check - ) - { - return; - } - - const long update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps(); - - auto it_update_hist = update_history_.begin(); - - for ( long t = update_history_.begin()->t_; - t <= ( update_history_.end() - 1 )->t_ and it_update_hist != update_history_.end(); - t += update_interval ) - { - if ( it_update_hist->t_ == t ) - { - ++it_update_hist; - } - else - { - // erase no longer needed entries for update intervals with no spikes sent to the target neuron - eprop_history_.erase( get_eprop_history( t ), get_eprop_history( t + update_interval ) ); - } - } - // erase no longer needed entries before the earliest current update - eprop_history_.erase( get_eprop_history( 0 ), get_eprop_history( update_history_.begin()->t_ ) ); -} - -template < typename HistEntryT > -void -EpropArchivingNode< HistEntryT >::erase_used_eprop_history( const long eprop_isi_trace_cutoff ) -{ - if ( eprop_history_.empty() // nothing to remove - or update_history_.size() < 2 // no time markers to check - ) - { - return; - } - - const long t_prev = ( update_history_.end() - 2 )->t_; - const long t_curr = ( update_history_.end() - 1 )->t_; - - if ( t_prev + eprop_isi_trace_cutoff < t_curr ) - { - // erase no longer needed entries to be ignored by trace cutoff - eprop_history_.erase( get_eprop_history( t_prev + eprop_isi_trace_cutoff ), get_eprop_history( t_curr ) ); - } - - // erase no longer needed entries before the earliest current update - eprop_history_.erase( - get_eprop_history( std::numeric_limits< long >::min() ), get_eprop_history( update_history_.begin()->t_ - 1 ) ); -} - -template < typename HistEntryT > -inline double -EpropArchivingNode< HistEntryT >::get_eprop_history_duration() const -{ - return Time::get_resolution().get_ms() * eprop_history_.size(); -} - -} // namespace nest - -#endif // EPROP_ARCHIVING_NODE_IMPL_H diff --git a/nestkernel/eprop_archiving_node_recurrent.h b/nestkernel/eprop_archiving_node_recurrent.h index a8872e3297..3442796b96 100644 --- a/nestkernel/eprop_archiving_node_recurrent.h +++ b/nestkernel/eprop_archiving_node_recurrent.h @@ -304,6 +304,272 @@ EpropArchivingNodeRecurrent< hist_shift_required >::history_shift_required_() co return hist_shift_required; } +template < bool hist_shift_required > +std::map< std::string, typename EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_function > + EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_funcs_ = { + { "piecewise_linear", + &EpropArchivingNodeRecurrent< hist_shift_required >::compute_piecewise_linear_surrogate_gradient }, + { "exponential", &EpropArchivingNodeRecurrent< hist_shift_required >::compute_exponential_surrogate_gradient }, + { "fast_sigmoid_derivative", + &EpropArchivingNodeRecurrent< hist_shift_required >::compute_fast_sigmoid_derivative_surrogate_gradient }, + { "arctan", &EpropArchivingNodeRecurrent< hist_shift_required >::compute_arctan_surrogate_gradient } + }; + +template < bool hist_shift_required > +EpropArchivingNodeRecurrent< hist_shift_required >::EpropArchivingNodeRecurrent() + : EpropArchivingNode() + , firing_rate_reg_( 0.0 ) + , f_av_( 0.0 ) + , n_spikes_( 0 ) +{ +} + +template < bool hist_shift_required > +EpropArchivingNodeRecurrent< hist_shift_required >::EpropArchivingNodeRecurrent( const EpropArchivingNodeRecurrent& n ) + : EpropArchivingNode( n ) + , firing_rate_reg_( n.firing_rate_reg_ ) + , f_av_( n.f_av_ ) + , n_spikes_( n.n_spikes_ ) +{ +} + +template < bool hist_shift_required > +typename EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_function +EpropArchivingNodeRecurrent< hist_shift_required >::find_surrogate_gradient( + const std::string& surrogate_gradient_function_name ) +{ + const auto found_entry_it = surrogate_gradient_funcs_.find( surrogate_gradient_function_name ); + + if ( found_entry_it != surrogate_gradient_funcs_.end() ) + { + return found_entry_it->second; + } + + std::string error_message = "Surrogate gradient / pseudo-derivate function surrogate_gradient_function from ["; + for ( const auto& surrogate_gradient_func : surrogate_gradient_funcs_ ) + { + error_message += " \"" + surrogate_gradient_func.first + "\","; + } + error_message.pop_back(); + error_message += " ] required."; + + throw BadProperty( error_message ); +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::compute_piecewise_linear_surrogate_gradient( const double r, + const double v_m, + const double v_th, + const double beta, + const double gamma ) +{ + if ( r > 0 ) + { + return 0.0; + } + + return gamma * std::max( 0.0, 1.0 - beta * std::abs( v_m - v_th ) ); +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::compute_exponential_surrogate_gradient( const double r, + const double v_m, + const double v_th, + const double beta, + const double gamma ) +{ + if ( r > 0 ) + { + return 0.0; + } + + return gamma * std::exp( -beta * std::abs( v_m - v_th ) ); +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::compute_fast_sigmoid_derivative_surrogate_gradient( const double r, + const double v_m, + const double v_th, + const double beta, + const double gamma ) +{ + if ( r > 0 ) + { + return 0.0; + } + + return gamma * std::pow( 1.0 + beta * std::abs( v_m - v_th ), -2 ); +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::compute_arctan_surrogate_gradient( const double r, + const double v_m, + const double v_th, + const double beta, + const double gamma ) +{ + if ( r > 0 ) + { + return 0.0; + } + + return gamma / M_PI * ( 1.0 / ( 1.0 + std::pow( beta * M_PI * ( v_m - v_th ), 2 ) ) ); +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::append_new_eprop_history_entry( const long time_step ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + eprop_history_.emplace_back( time_step, 0.0, 0.0, 0.0 ); +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::write_surrogate_gradient_to_history( const long time_step, + const double surrogate_gradient ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + auto it_hist = get_eprop_history( time_step ); + it_hist->surrogate_gradient_ = surrogate_gradient; +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::write_learning_signal_to_history( const long time_step, + const double learning_signal ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + long shift = delay_rec_out_ + delay_out_rec_; + + if constexpr ( hist_shift_required ) + { + shift += delay_out_norm_; + } + + + auto it_hist = get_eprop_history( time_step - shift ); + const auto it_hist_end = get_eprop_history( time_step - shift + delay_out_rec_ ); + + for ( ; it_hist != it_hist_end; ++it_hist ) + { + it_hist->learning_signal_ += learning_signal; + } +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::write_firing_rate_reg_to_history( const long t_current_update, + const double f_target, + const double c_reg ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + const double update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps(); + const double dt = Time::get_resolution().get_ms(); + const long shift = Time::get_resolution().get_steps(); + + const double f_av = n_spikes_ / update_interval; + const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step + const double firing_rate_reg = c_reg * ( f_av - f_target_ ) / update_interval; + + firing_rate_reg_history_.emplace_back( t_current_update + shift, firing_rate_reg ); +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::write_firing_rate_reg_to_history( const long time_step, + const double z, + const double f_target, + const double kappa_reg, + const double c_reg ) +{ + if ( eprop_indegree_ == 0 ) + { + return; + } + + const double dt = Time::get_resolution().get_ms(); + + const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step + + f_av_ = kappa_reg * f_av_ + ( 1.0 - kappa_reg ) * z / dt; + + firing_rate_reg_ = c_reg * ( f_av_ - f_target_ ); + + auto it_hist = get_eprop_history( time_step ); + it_hist->firing_rate_reg_ = firing_rate_reg_; +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::get_firing_rate_reg_history( const long time_step ) +{ + const auto it_hist = std::lower_bound( firing_rate_reg_history_.begin(), firing_rate_reg_history_.end(), time_step ); + assert( it_hist != firing_rate_reg_history_.end() ); + + return it_hist->firing_rate_reg_; +} + +template < bool hist_shift_required > +double +EpropArchivingNodeRecurrent< hist_shift_required >::get_learning_signal_from_history( const long time_step ) +{ + long shift = delay_rec_out_ + delay_out_rec_; + + if ( hist_shift_required ) + { + shift += delay_out_norm_; + } + + const auto it = get_eprop_history( time_step - shift ); + if ( it == eprop_history_.end() ) + { + return 0; + } + + return it->learning_signal_; +} + +template < bool hist_shift_required > +void +EpropArchivingNodeRecurrent< hist_shift_required >::erase_used_firing_rate_reg_history() +{ + auto it_update_hist = update_history_.begin(); + auto it_reg_hist = firing_rate_reg_history_.begin(); + + while ( it_update_hist != update_history_.end() and it_reg_hist != firing_rate_reg_history_.end() ) + { + if ( it_update_hist->access_counter_ == 0 ) + { + it_reg_hist = firing_rate_reg_history_.erase( it_reg_hist ); + } + else + { + ++it_reg_hist; + } + ++it_update_hist; + } +} } diff --git a/nestkernel/eprop_archiving_node_recurrent_impl.h b/nestkernel/eprop_archiving_node_recurrent_impl.h deleted file mode 100644 index 58dde7a87e..0000000000 --- a/nestkernel/eprop_archiving_node_recurrent_impl.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * eprop_archiving_node_recurrent_impl.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 . - * - */ - -// nestkernel -#include "eprop_archiving_node.h" -#include "eprop_archiving_node_impl.h" -#include "eprop_archiving_node_recurrent.h" -#include "kernel_manager.h" - -// sli -#include "dictutils.h" - -namespace nest -{ - -template < bool hist_shift_required > -std::map< std::string, typename EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_function > - EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_funcs_ = { - { "piecewise_linear", - &EpropArchivingNodeRecurrent< hist_shift_required >::compute_piecewise_linear_surrogate_gradient }, - { "exponential", &EpropArchivingNodeRecurrent< hist_shift_required >::compute_exponential_surrogate_gradient }, - { "fast_sigmoid_derivative", - &EpropArchivingNodeRecurrent< hist_shift_required >::compute_fast_sigmoid_derivative_surrogate_gradient }, - { "arctan", &EpropArchivingNodeRecurrent< hist_shift_required >::compute_arctan_surrogate_gradient } - }; - -template < bool hist_shift_required > -EpropArchivingNodeRecurrent< hist_shift_required >::EpropArchivingNodeRecurrent() - : EpropArchivingNode() - , firing_rate_reg_( 0.0 ) - , f_av_( 0.0 ) - , n_spikes_( 0 ) -{ -} - -template < bool hist_shift_required > -EpropArchivingNodeRecurrent< hist_shift_required >::EpropArchivingNodeRecurrent( const EpropArchivingNodeRecurrent& n ) - : EpropArchivingNode( n ) - , firing_rate_reg_( n.firing_rate_reg_ ) - , f_av_( n.f_av_ ) - , n_spikes_( n.n_spikes_ ) -{ -} - -template < bool hist_shift_required > -typename EpropArchivingNodeRecurrent< hist_shift_required >::surrogate_gradient_function -EpropArchivingNodeRecurrent< hist_shift_required >::find_surrogate_gradient( - const std::string& surrogate_gradient_function_name ) -{ - const auto found_entry_it = surrogate_gradient_funcs_.find( surrogate_gradient_function_name ); - - if ( found_entry_it != surrogate_gradient_funcs_.end() ) - { - return found_entry_it->second; - } - - std::string error_message = "Surrogate gradient / pseudo-derivate function surrogate_gradient_function from ["; - for ( const auto& surrogate_gradient_func : surrogate_gradient_funcs_ ) - { - error_message += " \"" + surrogate_gradient_func.first + "\","; - } - error_message.pop_back(); - error_message += " ] required."; - - throw BadProperty( error_message ); -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::compute_piecewise_linear_surrogate_gradient( const double r, - const double v_m, - const double v_th, - const double beta, - const double gamma ) -{ - if ( r > 0 ) - { - return 0.0; - } - - return gamma * std::max( 0.0, 1.0 - beta * std::abs( v_m - v_th ) ); -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::compute_exponential_surrogate_gradient( const double r, - const double v_m, - const double v_th, - const double beta, - const double gamma ) -{ - if ( r > 0 ) - { - return 0.0; - } - - return gamma * std::exp( -beta * std::abs( v_m - v_th ) ); -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::compute_fast_sigmoid_derivative_surrogate_gradient( const double r, - const double v_m, - const double v_th, - const double beta, - const double gamma ) -{ - if ( r > 0 ) - { - return 0.0; - } - - return gamma * std::pow( 1.0 + beta * std::abs( v_m - v_th ), -2 ); -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::compute_arctan_surrogate_gradient( const double r, - const double v_m, - const double v_th, - const double beta, - const double gamma ) -{ - if ( r > 0 ) - { - return 0.0; - } - - return gamma / M_PI * ( 1.0 / ( 1.0 + std::pow( beta * M_PI * ( v_m - v_th ), 2 ) ) ); -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::append_new_eprop_history_entry( const long time_step ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - eprop_history_.emplace_back( time_step, 0.0, 0.0, 0.0 ); -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::write_surrogate_gradient_to_history( const long time_step, - const double surrogate_gradient ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - auto it_hist = get_eprop_history( time_step ); - it_hist->surrogate_gradient_ = surrogate_gradient; -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::write_learning_signal_to_history( const long time_step, - const double learning_signal ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - long shift = delay_rec_out_ + delay_out_rec_; - - if constexpr ( hist_shift_required ) - { - shift += delay_out_norm_; - } - - - auto it_hist = get_eprop_history( time_step - shift ); - const auto it_hist_end = get_eprop_history( time_step - shift + delay_out_rec_ ); - - for ( ; it_hist != it_hist_end; ++it_hist ) - { - it_hist->learning_signal_ += learning_signal; - } -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::write_firing_rate_reg_to_history( const long t_current_update, - const double f_target, - const double c_reg ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - const double update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps(); - const double dt = Time::get_resolution().get_ms(); - const long shift = Time::get_resolution().get_steps(); - - const double f_av = n_spikes_ / update_interval; - const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step - const double firing_rate_reg = c_reg * ( f_av - f_target_ ) / update_interval; - - firing_rate_reg_history_.emplace_back( t_current_update + shift, firing_rate_reg ); -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::write_firing_rate_reg_to_history( const long time_step, - const double z, - const double f_target, - const double kappa_reg, - const double c_reg ) -{ - if ( eprop_indegree_ == 0 ) - { - return; - } - - const double dt = Time::get_resolution().get_ms(); - - const double f_target_ = f_target * dt; // convert from spikes/ms to spikes/step - - f_av_ = kappa_reg * f_av_ + ( 1.0 - kappa_reg ) * z / dt; - - firing_rate_reg_ = c_reg * ( f_av_ - f_target_ ); - - auto it_hist = get_eprop_history( time_step ); - it_hist->firing_rate_reg_ = firing_rate_reg_; -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::get_firing_rate_reg_history( const long time_step ) -{ - const auto it_hist = std::lower_bound( firing_rate_reg_history_.begin(), firing_rate_reg_history_.end(), time_step ); - assert( it_hist != firing_rate_reg_history_.end() ); - - return it_hist->firing_rate_reg_; -} - -template < bool hist_shift_required > -double -EpropArchivingNodeRecurrent< hist_shift_required >::get_learning_signal_from_history( const long time_step ) -{ - long shift = delay_rec_out_ + delay_out_rec_; - - if ( hist_shift_required ) - { - shift += delay_out_norm_; - } - - const auto it = get_eprop_history( time_step - shift ); - if ( it == eprop_history_.end() ) - { - return 0; - } - - return it->learning_signal_; -} - -template < bool hist_shift_required > -void -EpropArchivingNodeRecurrent< hist_shift_required >::erase_used_firing_rate_reg_history() -{ - auto it_update_hist = update_history_.begin(); - auto it_reg_hist = firing_rate_reg_history_.begin(); - - while ( it_update_hist != update_history_.end() and it_reg_hist != firing_rate_reg_history_.end() ) - { - if ( it_update_hist->access_counter_ == 0 ) - { - it_reg_hist = firing_rate_reg_history_.erase( it_reg_hist ); - } - else - { - ++it_reg_hist; - } - ++it_update_hist; - } -} - - -} // namespace nest diff --git a/nestkernel/event.cpp b/nestkernel/event.cpp index 6d33a5f615..ec67e07238 100644 --- a/nestkernel/event.cpp +++ b/nestkernel/event.cpp @@ -23,9 +23,9 @@ #include "event.h" // Includes from nestkernel: +#include "connection_manager.h" #include "kernel_manager.h" #include "node.h" -#include "secondary_event_impl.h" namespace nest { diff --git a/nestkernel/event_delivery_manager.cpp b/nestkernel/event_delivery_manager.cpp index 8ba790b740..fd87d011c8 100644 --- a/nestkernel/event_delivery_manager.cpp +++ b/nestkernel/event_delivery_manager.cpp @@ -28,15 +28,11 @@ // Includes from nestkernel: #include "connection_manager.h" -#include "connection_manager_impl.h" -#include "event_delivery_manager_impl.h" #include "kernel_manager.h" -#include "mpi_manager_impl.h" +#include "model_manager.h" #include "send_buffer_position.h" -#include "source.h" -#include "stopwatch_impl.h" +#include "simulation_manager.h" #include "vp_manager.h" -#include "vp_manager_impl.h" // Includes from sli: #include "dictutils.h" @@ -423,9 +419,9 @@ EventDeliveryManager::gather_spike_data_( std::vector< SpikeDataT >& send_buffer // We introduce an explicit barrier at this point to measure how long each process idles until all other processes // reached this point as well. This barrier is directly followed by another implicit barrier due to global // communication. - kernel().get_mpi_synchronization_stopwatch().start(); + kernel().simulation_manager.get_mpi_synchronization_stopwatch().start(); kernel().mpi_manager.synchronize(); - kernel().get_mpi_synchronization_stopwatch().stop(); + kernel().simulation_manager.get_mpi_synchronization_stopwatch().stop(); #endif // Given that we templatize by plain vs offgrid, this if should not be necessary, but ... @@ -802,9 +798,9 @@ EventDeliveryManager::gather_target_data( const size_t tid ) resize_send_recv_buffers_target_data(); } } // of omp master; (no barrier) - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); kernel().connection_manager.restore_source_table_entry_point( tid ); @@ -819,9 +815,9 @@ EventDeliveryManager::gather_target_data( const size_t tid ) set_complete_marker_target_data_( assigned_ranks, send_buffer_position ); } kernel().connection_manager.save_source_table_entry_point( tid ); - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); kernel().connection_manager.clean_source_table( tid ); #pragma omp master @@ -874,9 +870,9 @@ EventDeliveryManager::gather_target_data_compressed( const size_t tid ) resize_send_recv_buffers_target_data(); } } // of omp master; no barrier - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); TargetSendBufferPosition send_buffer_position( assigned_ranks, kernel().mpi_manager.get_send_recv_count_target_data_per_rank() ); @@ -891,9 +887,9 @@ EventDeliveryManager::gather_target_data_compressed( const size_t tid ) set_complete_marker_target_data_( assigned_ranks, send_buffer_position ); } - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); #pragma omp master { @@ -916,9 +912,9 @@ EventDeliveryManager::gather_target_data_compressed( const size_t tid ) { buffer_size_target_data_has_changed_ = kernel().mpi_manager.increase_buffer_size_target_data(); } // of omp master (no barrier) - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); } } // of while diff --git a/nestkernel/event_delivery_manager.h b/nestkernel/event_delivery_manager.h index dbdbe1483b..c50326bf38 100644 --- a/nestkernel/event_delivery_manager.h +++ b/nestkernel/event_delivery_manager.h @@ -25,7 +25,6 @@ // C++ includes: #include -#include #include // Includes from libnestutil: @@ -34,13 +33,16 @@ // Includes from nestkernel: #include "buffer_resize_log.h" +#include "connection_manager.h" #include "event.h" +#include "kernel_manager.h" #include "mpi_manager.h" // OffGridSpike #include "nest_time.h" #include "nest_types.h" #include "node.h" #include "per_thread_bool_indicator.h" #include "secondary_event.h" +#include "simulation_manager.h" #include "spike_data.h" #include "target_table.h" #include "vp_manager.h" @@ -531,6 +533,149 @@ EventDeliveryManager::get_slice_modulo( long d ) return slice_moduli_[ d ]; } +template < class EventT > +inline void +EventDeliveryManager::send_local_( Node& source, EventT& e, const long lag ) +{ + assert( not source.has_proxies() ); + e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( lag + 1 ) ); + e.set_sender( source ); + const size_t t = source.get_thread(); + const size_t ldid = source.get_local_device_id(); + kernel().connection_manager.send_from_device( t, ldid, e ); +} + +inline void +EventDeliveryManager::send_local_( Node& source, SecondaryEvent& e, const long ) +{ + assert( not source.has_proxies() ); + e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( 1 ) ); + e.set_sender( source ); + const size_t t = source.get_thread(); + const size_t ldid = source.get_local_device_id(); + kernel().connection_manager.send_from_device( t, ldid, e ); +} + +template < class EventT > +inline void +EventDeliveryManager::send( Node& source, EventT& e, const long lag ) +{ + send_local_( source, e, lag ); +} + +template <> +inline void +EventDeliveryManager::send< SpikeEvent >( Node& source, SpikeEvent& e, const long lag ) +{ + const size_t tid = source.get_thread(); + const size_t source_node_id = source.get_node_id(); + e.set_sender_node_id( source_node_id ); + if ( source.has_proxies() ) + { + local_spike_counter_[ tid ] += e.get_multiplicity(); + + e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( lag + 1 ) ); + e.set_sender( source ); + + if ( source.is_off_grid() ) + { + send_off_grid_remote( tid, e, lag ); + } + else + { + send_remote( tid, e, lag ); + } + kernel().connection_manager.send_to_devices( tid, source_node_id, e ); + } + else + { + send_local_( source, e, lag ); + } +} + +template <> +inline void +EventDeliveryManager::send< DSSpikeEvent >( Node& source, DSSpikeEvent& e, const long lag ) +{ + e.set_sender_node_id( source.get_node_id() ); + send_local_( source, e, lag ); +} + +inline void +EventDeliveryManager::send_remote( size_t tid, SpikeEvent& e, const long lag ) +{ + // Put the spike in a buffer for the remote machines + const size_t lid = kernel().vp_manager.node_id_to_lid( e.get_sender().get_node_id() ); + const auto& targets = kernel().connection_manager.get_remote_targets_of_local_node( tid, lid ); + + for ( const auto& target : targets ) + { + // Unroll spike multiplicity as plastic synapses only handle individual spikes. + for ( size_t i = 0; i < e.get_multiplicity(); ++i ) + { + ( *emitted_spikes_register_[ tid ] ).emplace_back( target, lag ); + } + } +} + +inline void +EventDeliveryManager::send_off_grid_remote( size_t tid, SpikeEvent& e, const long lag ) +{ + // Put the spike in a buffer for the remote machines + const size_t lid = kernel().vp_manager.node_id_to_lid( e.get_sender().get_node_id() ); + const auto& targets = kernel().connection_manager.get_remote_targets_of_local_node( tid, lid ); + + for ( const auto& target : targets ) + { + // Unroll spike multiplicity as plastic synapses only handle individual spikes. + for ( size_t i = 0; i < e.get_multiplicity(); ++i ) + { + ( *off_grid_emitted_spikes_register_[ tid ] ).emplace_back( target, lag, e.get_offset() ); + } + } +} + +inline void +EventDeliveryManager::send_secondary( Node& source, SecondaryEvent& e ) +{ + const size_t tid = kernel().vp_manager.get_thread_id(); + const size_t source_node_id = source.get_node_id(); + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + + if ( source.has_proxies() ) + { + + // We need to consider every synapse type this event supports to + // make sure also labeled and connection created by CopyModel are + // considered. + const std::set< synindex >& supported_syn_ids = e.get_supported_syn_ids(); + for ( const auto& syn_id : supported_syn_ids ) + { + const std::vector< size_t >& positions = + kernel().connection_manager.get_secondary_send_buffer_positions( tid, lid, syn_id ); + + for ( size_t i = 0; i < positions.size(); ++i ) + { + std::vector< unsigned int >::iterator it = send_buffer_secondary_events_.begin() + positions[ i ]; + e >> it; + } + } + kernel().connection_manager.send_to_devices( tid, source_node_id, e ); + } + else + { + send_local_( source, e, 0 ); // need to pass lag (last argument), but not + // used in template specialization, so pass + // zero as dummy value + } +} + +inline size_t +EventDeliveryManager::write_toggle() const +{ + return kernel().simulation_manager.get_slice() % 2; +} + } // namespace nest #endif /* EVENT_DELIVERY_MANAGER_H */ diff --git a/nestkernel/event_delivery_manager_impl.h b/nestkernel/event_delivery_manager_impl.h deleted file mode 100644 index 55310a24bd..0000000000 --- a/nestkernel/event_delivery_manager_impl.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * event_delivery_manager_impl.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 EVENT_DELIVERY_MANAGER_IMPL_H -#define EVENT_DELIVERY_MANAGER_IMPL_H - -#include "event_delivery_manager.h" - -// Includes from nestkernel: -#include "connection_manager_impl.h" -#include "kernel_manager.h" - -namespace nest -{ - -template < class EventT > -inline void -EventDeliveryManager::send_local_( Node& source, EventT& e, const long lag ) -{ - assert( not source.has_proxies() ); - e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( lag + 1 ) ); - e.set_sender( source ); - const size_t t = source.get_thread(); - const size_t ldid = source.get_local_device_id(); - kernel().connection_manager.send_from_device( t, ldid, e ); -} - -inline void -EventDeliveryManager::send_local_( Node& source, SecondaryEvent& e, const long ) -{ - assert( not source.has_proxies() ); - e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( 1 ) ); - e.set_sender( source ); - const size_t t = source.get_thread(); - const size_t ldid = source.get_local_device_id(); - kernel().connection_manager.send_from_device( t, ldid, e ); -} - -template < class EventT > -inline void -EventDeliveryManager::send( Node& source, EventT& e, const long lag ) -{ - send_local_( source, e, lag ); -} - -template <> -inline void -EventDeliveryManager::send< SpikeEvent >( Node& source, SpikeEvent& e, const long lag ) -{ - const size_t tid = source.get_thread(); - const size_t source_node_id = source.get_node_id(); - e.set_sender_node_id( source_node_id ); - if ( source.has_proxies() ) - { - local_spike_counter_[ tid ] += e.get_multiplicity(); - - e.set_stamp( kernel().simulation_manager.get_slice_origin() + Time::step( lag + 1 ) ); - e.set_sender( source ); - - if ( source.is_off_grid() ) - { - send_off_grid_remote( tid, e, lag ); - } - else - { - send_remote( tid, e, lag ); - } - kernel().connection_manager.send_to_devices( tid, source_node_id, e ); - } - else - { - send_local_( source, e, lag ); - } -} - -template <> -inline void -EventDeliveryManager::send< DSSpikeEvent >( Node& source, DSSpikeEvent& e, const long lag ) -{ - e.set_sender_node_id( source.get_node_id() ); - send_local_( source, e, lag ); -} - -inline void -EventDeliveryManager::send_remote( size_t tid, SpikeEvent& e, const long lag ) -{ - // Put the spike in a buffer for the remote machines - const size_t lid = kernel().vp_manager.node_id_to_lid( e.get_sender().get_node_id() ); - const auto& targets = kernel().connection_manager.get_remote_targets_of_local_node( tid, lid ); - - for ( const auto& target : targets ) - { - // Unroll spike multiplicity as plastic synapses only handle individual spikes. - for ( size_t i = 0; i < e.get_multiplicity(); ++i ) - { - ( *emitted_spikes_register_[ tid ] ).emplace_back( target, lag ); - } - } -} - -inline void -EventDeliveryManager::send_off_grid_remote( size_t tid, SpikeEvent& e, const long lag ) -{ - // Put the spike in a buffer for the remote machines - const size_t lid = kernel().vp_manager.node_id_to_lid( e.get_sender().get_node_id() ); - const auto& targets = kernel().connection_manager.get_remote_targets_of_local_node( tid, lid ); - - for ( const auto& target : targets ) - { - // Unroll spike multiplicity as plastic synapses only handle individual spikes. - for ( size_t i = 0; i < e.get_multiplicity(); ++i ) - { - ( *off_grid_emitted_spikes_register_[ tid ] ).emplace_back( target, lag, e.get_offset() ); - } - } -} - -inline void -EventDeliveryManager::send_secondary( Node& source, SecondaryEvent& e ) -{ - const size_t tid = kernel().vp_manager.get_thread_id(); - const size_t source_node_id = source.get_node_id(); - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - - if ( source.has_proxies() ) - { - - // We need to consider every synapse type this event supports to - // make sure also labeled and connection created by CopyModel are - // considered. - const std::set< synindex >& supported_syn_ids = e.get_supported_syn_ids(); - for ( const auto& syn_id : supported_syn_ids ) - { - const std::vector< size_t >& positions = - kernel().connection_manager.get_secondary_send_buffer_positions( tid, lid, syn_id ); - - for ( size_t i = 0; i < positions.size(); ++i ) - { - std::vector< unsigned int >::iterator it = send_buffer_secondary_events_.begin() + positions[ i ]; - e >> it; - } - } - kernel().connection_manager.send_to_devices( tid, source_node_id, e ); - } - else - { - send_local_( source, e, 0 ); // need to pass lag (last argument), but not - // used in template specialization, so pass - // zero as dummy value - } -} - -inline size_t -EventDeliveryManager::write_toggle() const -{ - return kernel().simulation_manager.get_slice() % 2; -} - - -} // of namespace nest - -#endif diff --git a/nestkernel/free_layer.h b/nestkernel/free_layer.h index 40b1c972cc..786c2ba075 100644 --- a/nestkernel/free_layer.h +++ b/nestkernel/free_layer.h @@ -30,13 +30,13 @@ // Includes from nestkernel: #include "nest_names.h" +#include "node_manager.h" // Includes from sli: #include "dictutils.h" // Includes from spatial: #include "layer.h" -#include "ntree_impl.h" namespace nest { diff --git a/nestkernel/genericmodel.h b/nestkernel/genericmodel.h index a6f5ddc9cb..225cb334e6 100644 --- a/nestkernel/genericmodel.h +++ b/nestkernel/genericmodel.h @@ -23,10 +23,8 @@ #ifndef GENERICMODEL_H #define GENERICMODEL_H -// C++ includes: -#include - // Includes from nestkernel: +#include "logging_manager.h" #include "model.h" namespace nest @@ -281,6 +279,24 @@ GenericModel< ElementT >::get_model_id() { return proto_.get_model_id(); } + +template < typename ElementT > +void +GenericModel< ElementT >::deprecation_warning( const std::string& caller ) +{ + if ( deprecation_warning_issued_ or deprecation_info_.empty() ) + { + return; + } + + if ( not deprecation_info_.empty() ) + { + LOG( M_DEPRECATED, caller, "Model " + get_name() + " is deprecated in " + deprecation_info_ + "." ); + } + + deprecation_warning_issued_ = true; } +} // namespace nest + #endif diff --git a/nestkernel/genericmodel_impl.h b/nestkernel/genericmodel_impl.h deleted file mode 100644 index db1d0edc3f..0000000000 --- a/nestkernel/genericmodel_impl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * genericmodel_impl.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 GENERICMODEL_IMPL_H -#define GENERICMODEL_IMPL_H - -#include "genericmodel.h" - -// Includes from nestkernel: -#include "kernel_manager.h" -#include "logging_manager.h" - -namespace nest -{ - -template < typename ElementT > -void -GenericModel< ElementT >::deprecation_warning( const std::string& caller ) -{ - if ( deprecation_warning_issued_ or deprecation_info_.empty() ) - { - return; - } - - if ( not deprecation_info_.empty() ) - { - LOG( M_DEPRECATED, caller, "Model " + get_name() + " is deprecated in " + deprecation_info_ + "." ); - } - - deprecation_warning_issued_ = true; -} -} -#endif diff --git a/nestkernel/io_manager.cpp b/nestkernel/io_manager.cpp index 2d6bdf27e5..4633285782 100644 --- a/nestkernel/io_manager.cpp +++ b/nestkernel/io_manager.cpp @@ -38,11 +38,12 @@ #include "logging.h" // Includes from nestkernel: -#include "io_manager_impl.h" #include "kernel_manager.h" +#include "logging_manager.h" #include "recording_backend_ascii.h" #include "recording_backend_memory.h" #include "recording_backend_screen.h" + #ifdef HAVE_MPI #include "recording_backend_mpi.h" #include "stimulation_backend_mpi.h" diff --git a/nestkernel/io_manager.h b/nestkernel/io_manager.h index ea4be311bd..a6dcb20a4b 100644 --- a/nestkernel/io_manager.h +++ b/nestkernel/io_manager.h @@ -24,16 +24,23 @@ #define IO_MANAGER_H // C++ includes: +#include #include +#include // Includes from libnestutil: +#include "exceptions.h" #include "manager_interface.h" -#include "recording_backend.h" -#include "stimulation_backend.h" +// NOTE: Use forward declarations to avoid circular dependencies namespace nest { +class RecordingBackend; +class StimulationBackend; +class RecordingDevice; +class StimulationDevice; +class Event; /** * Manager to handle everything related to input and output. @@ -166,24 +173,52 @@ class IOManager : public ManagerInterface std::map< Name, StimulationBackend* > stimulation_backends_; }; -} // namespace nest - inline const std::string& -nest::IOManager::get_data_path() const +IOManager::get_data_path() const { return data_path_; } inline const std::string& -nest::IOManager::get_data_prefix() const +IOManager::get_data_prefix() const { return data_prefix_; } inline bool -nest::IOManager::overwrite_files() const +IOManager::overwrite_files() const { return overwrite_files_; } +template < class RecordingBackendT > +void +IOManager::register_recording_backend( const Name name ) +{ + if ( recording_backends_.find( name ) != recording_backends_.end() ) + { + throw BackendAlreadyRegistered( name.toString() ); + } + + RecordingBackendT* recording_backend = new RecordingBackendT(); + recording_backend->pre_run_hook(); + recording_backends_.insert( std::make_pair( name, recording_backend ) ); +} + +template < class StimulationBackendT > +void +IOManager::register_stimulation_backend( const Name name ) +{ + if ( stimulation_backends_.find( name ) != stimulation_backends_.end() ) + { + throw BackendAlreadyRegistered( name.toString() ); + } + + StimulationBackendT* stimulation_backend = new StimulationBackendT(); + stimulation_backend->pre_run_hook(); + stimulation_backends_.insert( std::make_pair( name, stimulation_backend ) ); +} + +} // namespace nest + #endif /* #ifndef IO_MANAGER_H */ diff --git a/nestkernel/io_manager_impl.h b/nestkernel/io_manager_impl.h deleted file mode 100644 index 9c631b4345..0000000000 --- a/nestkernel/io_manager_impl.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * io_manager_impl.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 IO_MANAGER_IMPL_H -#define IO_MANAGER_IMPL_H - -#include "io_manager.h" - -namespace nest -{ - -template < class RecordingBackendT > -void -IOManager::register_recording_backend( const Name name ) -{ - if ( recording_backends_.find( name ) != recording_backends_.end() ) - { - throw BackendAlreadyRegistered( name.toString() ); - } - - RecordingBackendT* recording_backend = new RecordingBackendT(); - recording_backend->pre_run_hook(); - recording_backends_.insert( std::make_pair( name, recording_backend ) ); -} - -template < class StimulationBackendT > -void -IOManager::register_stimulation_backend( const Name name ) -{ - if ( stimulation_backends_.find( name ) != stimulation_backends_.end() ) - { - throw BackendAlreadyRegistered( name.toString() ); - } - - StimulationBackendT* stimulation_backend = new StimulationBackendT(); - stimulation_backend->pre_run_hook(); - stimulation_backends_.insert( std::make_pair( name, stimulation_backend ) ); -} - -} // namespace nest - -#endif /* #ifndef IO_MANAGER_IMPL_H */ diff --git a/nestkernel/kernel_manager.cpp b/nestkernel/kernel_manager.cpp index e31cea89b4..b4cb7329ba 100644 --- a/nestkernel/kernel_manager.cpp +++ b/nestkernel/kernel_manager.cpp @@ -21,12 +21,29 @@ */ #include "kernel_manager.h" -#include "stopwatch_impl.h" -nest::KernelManager* nest::KernelManager::kernel_manager_instance_ = nullptr; +// Include concrete manager headers only in the implementation. +#include "connection_manager.h" +#include "event_delivery_manager.h" +#include "io_manager.h" +#include "logging_manager.h" +#include "model_manager.h" +#include "modelrange_manager.h" +#include "module_manager.h" +#include "mpi_manager.h" +#include "music_manager.h" +#include "node_manager.h" +#include "random_manager.h" +#include "simulation_manager.h" +#include "sp_manager.h" +#include "vp_manager.h" + +namespace nest +{ +KernelManager* KernelManager::kernel_manager_instance_ = nullptr; void -nest::KernelManager::create_kernel_manager() +KernelManager::create_kernel_manager() { #pragma omp master { @@ -40,28 +57,28 @@ nest::KernelManager::create_kernel_manager() } void -nest::KernelManager::destroy_kernel_manager() +KernelManager::destroy_kernel_manager() { kernel_manager_instance_->logging_manager.set_logging_level( M_QUIET ); delete kernel_manager_instance_; } -nest::KernelManager::KernelManager() +KernelManager::KernelManager() : fingerprint_( 0 ) - , logging_manager() - , mpi_manager() - , vp_manager() - , module_manager() - , random_manager() - , simulation_manager() - , modelrange_manager() - , connection_manager() - , sp_manager() - , event_delivery_manager() - , io_manager() - , model_manager() - , music_manager() - , node_manager() + , logging_manager( *new LoggingManager() ) + , mpi_manager( *new MPIManager() ) + , vp_manager( *new VPManager() ) + , module_manager( *new ModuleManager() ) + , random_manager( *new RandomManager() ) + , simulation_manager( *new SimulationManager() ) + , modelrange_manager( *new ModelRangeManager() ) + , connection_manager( *new ConnectionManager() ) + , sp_manager( *new SPManager() ) + , event_delivery_manager( *new EventDeliveryManager() ) + , io_manager( *new IOManager() ) + , model_manager( *new ModelManager() ) + , music_manager( *new MUSICManager() ) + , node_manager( *new NodeManager() ) , managers( { &logging_manager, &mpi_manager, &vp_manager, @@ -80,22 +97,27 @@ nest::KernelManager::KernelManager() { } -nest::KernelManager::~KernelManager() +KernelManager::~KernelManager() { + if ( initialized_ ) + { + finalize(); + } + + for ( auto manager : managers ) + { + delete manager; + } } void -nest::KernelManager::initialize() +KernelManager::initialize() { for ( auto& manager : managers ) { manager->initialize( /* adjust_number_of_threads_or_rng_only */ false ); } - sw_omp_synchronization_construction_.reset(); - sw_omp_synchronization_simulation_.reset(); - sw_mpi_synchronization_.reset(); - ++fingerprint_; initialized_ = true; FULL_LOGGING_ONLY( dump_.open( @@ -103,47 +125,44 @@ nest::KernelManager::initialize() } void -nest::KernelManager::prepare() +KernelManager::prepare() { - for ( auto& manager : managers ) + for ( auto manager : managers ) { manager->prepare(); } - - sw_omp_synchronization_simulation_.reset(); - sw_mpi_synchronization_.reset(); } void -nest::KernelManager::cleanup() +KernelManager::cleanup() { - for ( auto&& m_it = managers.rbegin(); m_it != managers.rend(); ++m_it ) + for ( auto it = managers.rbegin(); it != managers.rend(); ++it ) { - ( *m_it )->cleanup(); + ( *it )->cleanup(); } } void -nest::KernelManager::finalize() +KernelManager::finalize() { FULL_LOGGING_ONLY( dump_.close(); ) - for ( auto&& m_it = managers.rbegin(); m_it != managers.rend(); ++m_it ) + for ( auto it = managers.rbegin(); it != managers.rend(); ++it ) { - ( *m_it )->finalize( /* adjust_number_of_threads_or_rng_only */ false ); + ( *it )->finalize( /* adjust_number_of_threads_or_rng_only */ false ); } initialized_ = false; } void -nest::KernelManager::reset() +KernelManager::reset() { finalize(); initialize(); } void -nest::KernelManager::change_number_of_threads( size_t new_num_threads ) +KernelManager::change_number_of_threads( size_t new_num_threads ) { // Inputs are checked in VPManager::set_status(). // Just double check here that all values are legal. @@ -152,10 +171,9 @@ nest::KernelManager::change_number_of_threads( size_t new_num_threads ) assert( not simulation_manager.has_been_simulated() ); assert( not sp_manager.is_structural_plasticity_enabled() or new_num_threads == 1 ); - // Finalize in reverse order of initialization with old thread number set - for ( auto mgr_it = managers.rbegin(); mgr_it != managers.rend(); ++mgr_it ) + for ( auto it = managers.rbegin(); it != managers.rend(); ++it ) { - ( *mgr_it )->finalize( /* adjust_number_of_threads_or_rng_only */ true ); + ( *it )->finalize( /* adjust_number_of_threads_or_rng_only */ true ); } vp_manager.set_num_threads( new_num_threads ); @@ -176,14 +194,10 @@ nest::KernelManager::change_number_of_threads( size_t new_num_threads ) kernel().simulation_manager.reset_timers_for_dynamics(); kernel().event_delivery_manager.reset_timers_for_preparation(); kernel().event_delivery_manager.reset_timers_for_dynamics(); - - sw_omp_synchronization_construction_.reset(); - sw_omp_synchronization_simulation_.reset(); - sw_mpi_synchronization_.reset(); } void -nest::KernelManager::set_status( const DictionaryDatum& dict ) +KernelManager::set_status( const DictionaryDatum& dict ) { assert( is_initialized() ); @@ -194,7 +208,7 @@ nest::KernelManager::set_status( const DictionaryDatum& dict ) } void -nest::KernelManager::get_status( DictionaryDatum& dict ) +KernelManager::get_status( DictionaryDatum& dict ) { assert( is_initialized() ); @@ -202,16 +216,10 @@ nest::KernelManager::get_status( DictionaryDatum& dict ) { manager->get_status( dict ); } - - sw_omp_synchronization_construction_.get_status( - dict, names::time_omp_synchronization_construction, names::time_omp_synchronization_construction_cpu ); - sw_omp_synchronization_simulation_.get_status( - dict, names::time_omp_synchronization_simulation, names::time_omp_synchronization_simulation_cpu ); - sw_mpi_synchronization_.get_status( dict, names::time_mpi_synchronization, names::time_mpi_synchronization_cpu ); } void -nest::KernelManager::write_to_dump( const std::string& msg ) +KernelManager::write_to_dump( const std::string& msg ) { #pragma omp critical // In critical section to avoid any garbling of output. @@ -219,3 +227,5 @@ nest::KernelManager::write_to_dump( const std::string& msg ) dump_ << msg << std::endl << std::flush; } } + +} // namespace nest diff --git a/nestkernel/kernel_manager.h b/nestkernel/kernel_manager.h index abd225e836..05411cbb65 100644 --- a/nestkernel/kernel_manager.h +++ b/nestkernel/kernel_manager.h @@ -23,29 +23,9 @@ #ifndef KERNEL_MANAGER_H #define KERNEL_MANAGER_H -// Includes from libnestutil -#include "config.h" - -// Includes from nestkernel: -#include "connection_manager.h" -#include "event_delivery_manager.h" -#include "io_manager.h" -#include "logging_manager.h" -#include "model_manager.h" -#include "modelrange_manager.h" -#include "module_manager.h" -#include "mpi_manager.h" -#include "music_manager.h" -#include "node_manager.h" -#include "random_manager.h" -#include "simulation_manager.h" -#include "sp_manager.h" -#include "vp_manager.h" - // Includes from sli: #include "dictdatum.h" -#include "compose.hpp" #include /** @BeginDocumentation @@ -188,9 +168,26 @@ namespace nest { +// Forward declarations to avoid pulling all manager headers here. +class LoggingManager; +class MPIManager; +class VPManager; +class ModuleManager; +class RandomManager; +class SimulationManager; +class ModelRangeManager; +class ConnectionManager; +class SPManager; +class EventDeliveryManager; +class IOManager; +class ModelManager; +class MUSICManager; +class NodeManager; + +class ManagerInterface; + class KernelManager { -private: KernelManager(); ~KernelManager(); @@ -272,41 +269,21 @@ class KernelManager * NodeManager is last to ensure all model structures are in place before it is initialized. * @{ */ - LoggingManager logging_manager; - MPIManager mpi_manager; - VPManager vp_manager; - ModuleManager module_manager; - RandomManager random_manager; - SimulationManager simulation_manager; - ModelRangeManager modelrange_manager; - ConnectionManager connection_manager; - SPManager sp_manager; - EventDeliveryManager event_delivery_manager; - IOManager io_manager; - ModelManager model_manager; - MUSICManager music_manager; - NodeManager node_manager; - /**@}*/ - - //! Get the stopwatch to measure the time each thread is idle during network construction. - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded >& - get_omp_synchronization_construction_stopwatch() - { - return sw_omp_synchronization_construction_; - } - - //! Get the stopwatch to measure the time each thread is idle during simulation. - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded >& - get_omp_synchronization_simulation_stopwatch() - { - return sw_omp_synchronization_simulation_; - } - - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::MasterOnly >& - get_mpi_synchronization_stopwatch() - { - return sw_mpi_synchronization_; - } + // Property-like access to managers (public references). + LoggingManager& logging_manager; + MPIManager& mpi_manager; + VPManager& vp_manager; + ModuleManager& module_manager; + RandomManager& random_manager; + SimulationManager& simulation_manager; + ModelRangeManager& modelrange_manager; + ConnectionManager& connection_manager; + SPManager& sp_manager; + EventDeliveryManager& event_delivery_manager; + IOManager& io_manager; + ModelManager& model_manager; + MUSICManager& music_manager; + NodeManager& node_manager; private: //! All managers, order determines initialization and finalization order (latter backwards) @@ -314,39 +291,35 @@ class KernelManager bool initialized_; //!< true if the kernel is initialized std::ofstream dump_; //!< for FULL_LOGGING output - - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_omp_synchronization_construction_; - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_omp_synchronization_simulation_; - Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::MasterOnly > sw_mpi_synchronization_; }; KernelManager& kernel(); -} // namespace nest - -inline nest::KernelManager& -nest::KernelManager::get_kernel_manager() +inline KernelManager& +KernelManager::get_kernel_manager() { assert( kernel_manager_instance_ ); return *kernel_manager_instance_; } -inline nest::KernelManager& -nest::kernel() +inline KernelManager& +kernel() { return KernelManager::get_kernel_manager(); } inline bool -nest::KernelManager::is_initialized() const +KernelManager::is_initialized() const { return initialized_; } inline unsigned long -nest::KernelManager::get_fingerprint() const +KernelManager::get_fingerprint() const { return fingerprint_; } +} // namespace nest + #endif /* KERNEL_MANAGER_H */ diff --git a/nestkernel/layer.cpp b/nestkernel/layer.cpp index d8236b26a7..ccd766c5f4 100644 --- a/nestkernel/layer.cpp +++ b/nestkernel/layer.cpp @@ -34,11 +34,9 @@ #include "integerdatum.h" // Includes from spatial: -#include "connection_creator_impl.h" #include "free_layer.h" #include "grid_layer.h" #include "layer_impl.h" -#include "mask_impl.h" #include "spatial.h" namespace nest diff --git a/nestkernel/layer.h b/nestkernel/layer.h index 7adf212118..8e425e896d 100644 --- a/nestkernel/layer.h +++ b/nestkernel/layer.h @@ -34,7 +34,9 @@ #include "nest_types.h" // Includes from sli: +#include "booldatum.h" #include "dictutils.h" +#include "grid_mask.h" // Includes from spatial: #include "connection_creator.h" @@ -44,6 +46,9 @@ namespace nest { +template < int D > +class GridLayer; + class AbstractLayer; typedef std::shared_ptr< AbstractLayer > AbstractLayerPTR; @@ -522,174 +527,6 @@ class MaskedLayer MaskDatum mask_; }; -inline void -AbstractLayer::set_node_collection( NodeCollectionPTR node_collection ) -{ - node_collection_ = node_collection; -} - - -inline NodeCollectionPTR -AbstractLayer::get_node_collection() -{ - return node_collection_; -} - -template < int D > -inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, - const MaskDatum& maskd, - bool allow_oversized, - NodeCollectionPTR node_collection ) - : mask_( maskd ) -{ - ntree_ = layer.get_global_positions_ntree( node_collection ); - - check_mask_( layer, allow_oversized ); -} - -template < int D > -inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, - const MaskDatum& maskd, - bool allow_oversized, - Layer< D >& target, - NodeCollectionPTR node_collection ) - : mask_( maskd ) -{ - ntree_ = layer.get_global_positions_ntree( - target.get_periodic_mask(), target.get_lower_left(), target.get_extent(), node_collection ); - - check_mask_( target, allow_oversized ); - mask_ = new ConverseMask< D >( dynamic_cast< const Mask< D >& >( *mask_ ) ); -} - -template < int D > -inline MaskedLayer< D >::~MaskedLayer() -{ -} - -template < int D > -inline typename Ntree< D, size_t >::masked_iterator -MaskedLayer< D >::begin( const Position< D >& anchor ) -{ - try - { - return ntree_->masked_begin( dynamic_cast< const Mask< D >& >( *mask_ ), anchor ); - } - catch ( std::bad_cast& e ) - { - throw BadProperty( "Mask is incompatible with layer." ); - } -} - -template < int D > -inline typename Ntree< D, size_t >::masked_iterator -MaskedLayer< D >::end() -{ - return ntree_->masked_end(); -} - -template < int D > -inline Layer< D >::Layer() -{ - // Default center (0,0) and extent (1,1) - for ( int i = 0; i < D; ++i ) - { - lower_left_[ i ] = -0.5; - extent_[ i ] = 1.0; - } -} - -template < int D > -inline Layer< D >::Layer( const Layer& other_layer ) - : AbstractLayer( other_layer ) - , lower_left_( other_layer.lower_left_ ) - , extent_( other_layer.extent_ ) - , periodic_( other_layer.periodic_ ) -{ -} - -template < int D > -inline Layer< D >::~Layer() -{ - if ( cached_ntree_md_ == get_metadata() ) - { - clear_ntree_cache_(); - } - - if ( cached_vector_md_ == get_metadata() ) - { - clear_vector_cache_(); - } -} - -template < int D > -inline Position< D > -Layer< D >::compute_displacement( const Position< D >& from_pos, const size_t to_lid ) const -{ - return compute_displacement( from_pos, get_position( to_lid ) ); -} - -template < int D > -inline std::vector< double > -Layer< D >::compute_displacement( const std::vector< double >& from_pos, const size_t to_lid ) const -{ - return std::vector< double >( compute_displacement( Position< D >( from_pos ), to_lid ).get_vector() ); -} - -template < int D > -inline double -Layer< D >::compute_distance( const Position< D >& from_pos, const size_t lid ) const -{ - return compute_displacement( from_pos, lid ).length(); -} - -template < int D > -inline double -Layer< D >::compute_distance( const std::vector< double >& from_pos, const size_t lid ) const -{ - return compute_displacement( Position< D >( from_pos ), lid ).length(); -} - -template < int D > -inline double -Layer< D >::compute_distance( const std::vector< double >& from_pos, const std::vector< double >& to_pos ) const -{ - double squared_displacement = 0; - for ( unsigned int i = 0; i < D; ++i ) - { - const double displacement = compute_displacement( from_pos, to_pos, i ); - squared_displacement += displacement * displacement; - } - return std::sqrt( squared_displacement ); -} - -template < int D > -inline std::vector< double > -Layer< D >::get_position_vector( const size_t sind ) const -{ - return get_position( sind ).get_vector(); -} - -template < int D > -inline void -Layer< D >::clear_ntree_cache_() const -{ - cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >(); - cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); -} - -template < int D > -inline void -Layer< D >::clear_vector_cache_() const -{ - if ( cached_vector_ != 0 ) - { - delete cached_vector_; - } - cached_vector_ = 0; - cached_vector_md_ = NodeCollectionMetadataPTR( nullptr ); -} - } // namespace nest #endif diff --git a/nestkernel/layer_impl.h b/nestkernel/layer_impl.h index e24f571d08..7f96d0e44b 100644 --- a/nestkernel/layer_impl.h +++ b/nestkernel/layer_impl.h @@ -19,23 +19,179 @@ * along with NEST. If not, see . * */ +#include "grid_layer.h" +#include "layer.h" -#ifndef LAYER_IMPL_H -#define LAYER_IMPL_H +namespace nest +{ -#include "layer.h" +inline void +AbstractLayer::set_node_collection( NodeCollectionPTR node_collection ) +{ + node_collection_ = node_collection; +} -// Includes from nestkernel: -#include "booldatum.h" -#include "nest_datums.h" -#include "node_collection.h" -// Includes from spatial: -#include "grid_layer.h" -#include "grid_mask.h" +inline NodeCollectionPTR +AbstractLayer::get_node_collection() +{ + return node_collection_; +} -namespace nest +template < int D > +inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, + const MaskDatum& maskd, + bool allow_oversized, + NodeCollectionPTR node_collection ) + : mask_( maskd ) +{ + ntree_ = layer.get_global_positions_ntree( node_collection ); + + check_mask_( layer, allow_oversized ); +} + +template < int D > +inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, + const MaskDatum& maskd, + bool allow_oversized, + Layer< D >& target, + NodeCollectionPTR node_collection ) + : mask_( maskd ) +{ + ntree_ = layer.get_global_positions_ntree( + target.get_periodic_mask(), target.get_lower_left(), target.get_extent(), node_collection ); + + check_mask_( target, allow_oversized ); + mask_ = new ConverseMask< D >( dynamic_cast< const Mask< D >& >( *mask_ ) ); +} + +template < int D > +inline MaskedLayer< D >::~MaskedLayer() { +} + +template < int D > +inline typename Ntree< D, size_t >::masked_iterator +MaskedLayer< D >::begin( const Position< D >& anchor ) +{ + try + { + return ntree_->masked_begin( dynamic_cast< const Mask< D >& >( *mask_ ), anchor ); + } + catch ( std::bad_cast& e ) + { + throw BadProperty( "Mask is incompatible with layer." ); + } +} + +template < int D > +inline typename Ntree< D, size_t >::masked_iterator +MaskedLayer< D >::end() +{ + return ntree_->masked_end(); +} + +template < int D > +inline Layer< D >::Layer() +{ + // Default center (0,0) and extent (1,1) + for ( int i = 0; i < D; ++i ) + { + lower_left_[ i ] = -0.5; + extent_[ i ] = 1.0; + } +} + +template < int D > +inline Layer< D >::Layer( const Layer& other_layer ) + : AbstractLayer( other_layer ) + , lower_left_( other_layer.lower_left_ ) + , extent_( other_layer.extent_ ) + , periodic_( other_layer.periodic_ ) +{ +} + +template < int D > +inline Layer< D >::~Layer() +{ + if ( cached_ntree_md_ == get_metadata() ) + { + clear_ntree_cache_(); + } + + if ( cached_vector_md_ == get_metadata() ) + { + clear_vector_cache_(); + } +} + +template < int D > +inline Position< D > +Layer< D >::compute_displacement( const Position< D >& from_pos, const size_t to_lid ) const +{ + return compute_displacement( from_pos, get_position( to_lid ) ); +} + +template < int D > +inline std::vector< double > +Layer< D >::compute_displacement( const std::vector< double >& from_pos, const size_t to_lid ) const +{ + return std::vector< double >( compute_displacement( Position< D >( from_pos ), to_lid ).get_vector() ); +} + +template < int D > +inline double +Layer< D >::compute_distance( const Position< D >& from_pos, const size_t lid ) const +{ + return compute_displacement( from_pos, lid ).length(); +} + +template < int D > +inline double +Layer< D >::compute_distance( const std::vector< double >& from_pos, const size_t lid ) const +{ + return compute_displacement( Position< D >( from_pos ), lid ).length(); +} + +template < int D > +inline double +Layer< D >::compute_distance( const std::vector< double >& from_pos, const std::vector< double >& to_pos ) const +{ + double squared_displacement = 0; + for ( unsigned int i = 0; i < D; ++i ) + { + const double displacement = compute_displacement( from_pos, to_pos, i ); + squared_displacement += displacement * displacement; + } + return std::sqrt( squared_displacement ); +} + +template < int D > +inline std::vector< double > +Layer< D >::get_position_vector( const size_t sind ) const +{ + return get_position( sind ).get_vector(); +} + +template < int D > +inline void +Layer< D >::clear_ntree_cache_() const +{ + cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >(); + cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); +} + +template < int D > +inline void +Layer< D >::clear_vector_cache_() const +{ + if ( cached_vector_ != 0 ) + { + delete cached_vector_; + } + cached_vector_ = 0; + cached_vector_md_ = NodeCollectionMetadataPTR( nullptr ); +} template < int D > std::shared_ptr< Ntree< D, size_t > > Layer< D >::cached_ntree_; @@ -443,5 +599,3 @@ MaskedLayer< D >::check_mask_( Layer< D >& layer, bool allow_oversized ) } } // namespace nest - -#endif diff --git a/nestkernel/mask.h b/nestkernel/mask.h index 33b4c20c3b..813960cf75 100644 --- a/nestkernel/mask.h +++ b/nestkernel/mask.h @@ -1008,6 +1008,488 @@ EllipseMask< D >::EllipseMask( const DictionaryDatum& d ) create_bbox_(); } +template < int D > +AbstractMask* +Mask< D >::intersect_mask( const AbstractMask& other ) const +{ + const Mask* other_d = dynamic_cast< const Mask* >( &other ); + if ( other_d == 0 ) + { + throw BadProperty( "Masks must have same number of dimensions." ); + } + return new IntersectionMask< D >( *this, *other_d ); +} + +template < int D > +AbstractMask* +Mask< D >::union_mask( const AbstractMask& other ) const +{ + const Mask* other_d = dynamic_cast< const Mask* >( &other ); + if ( other_d == 0 ) + { + throw BadProperty( "Masks must have same number of dimensions." ); + } + return new UnionMask< D >( *this, *other_d ); +} + +template < int D > +AbstractMask* +Mask< D >::minus_mask( const AbstractMask& other ) const +{ + const Mask* other_d = dynamic_cast< const Mask* >( &other ); + if ( other_d == 0 ) + { + throw BadProperty( "Masks must have same number of dimensions." ); + } + return new DifferenceMask< D >( *this, *other_d ); +} + +template < int D > +bool +Mask< D >::inside( const std::vector< double >& pt ) const +{ + return inside( Position< D >( pt ) ); +} + +template < int D > +bool +Mask< D >::outside( const Box< D >& b ) const +{ + Box< D > bb = get_bbox(); + for ( int i = 0; i < D; ++i ) + { + if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] ) + { + return true; + } + } + return false; +} + +template < int D > +bool +BoxMask< D >::inside( const Box< D >& b ) const +{ + return ( inside( b.lower_left ) and inside( b.upper_right ) ); +} + +template < int D > +bool +BoxMask< D >::outside( const Box< D >& b ) const +{ + // Note: There could be some inconsistencies with the boundaries. For the + // inside() function we had to add an epsilon because of rounding errors that + // can occur if node IDs are on the boundary if we have rotation. This might lead + // to overlap of the inside and outside functions. None of the tests have + // picked up any problems with this potential overlap as of yet (autumn 2017), + // so we don't know if it is an actual problem. + for ( int i = 0; i < D; ++i ) + { + if ( b.upper_right[ i ] < min_values_[ i ] or b.lower_left[ i ] > max_values_[ i ] ) + { + return true; + } + } + return false; +} + +template < int D > +Box< D > +BoxMask< D >::get_bbox() const +{ + return Box< D >( min_values_, max_values_ ); +} + +template < int D > +Mask< D >* +BoxMask< D >::clone() const +{ + return new BoxMask( *this ); +} + +template < int D > +DictionaryDatum +BoxMask< D >::get_dict() const +{ + DictionaryDatum d( new Dictionary ); + DictionaryDatum maskd( new Dictionary ); + def< DictionaryDatum >( d, get_name(), maskd ); + def< std::vector< double > >( maskd, names::lower_left, lower_left_.get_vector() ); + def< std::vector< double > >( maskd, names::upper_right, upper_right_.get_vector() ); + def< double >( maskd, names::azimuth_angle, azimuth_angle_ ); + def< double >( maskd, names::polar_angle, polar_angle_ ); + return d; +} + +template < int D > +bool +BallMask< D >::inside( const Position< D >& p ) const +{ + // Optimizing by trying to avoid expensive calculations. + double dim_sum = 0; + // First check each dimension + for ( int i = 0; i < D; ++i ) + { + const double di = std::abs( p[ i ] - center_[ i ] ); + if ( di > radius_ ) + { + return false; + } + dim_sum += di; + } + // Next, check if we are inside a diamond (rotated square), which fits inside the ball. + if ( dim_sum <= radius_ ) + { + return true; + } + // Point must be somewhere between the ball mask edge and the diamond edge, + // revert to expensive calculation in this case. + return ( p - center_ ).length() <= radius_; +} + +template < int D > +bool +BallMask< D >::outside( const Box< D >& b ) const +{ + // Currently only checks if the box is outside the bounding box of + // the ball. This could be made more refined. + for ( int i = 0; i < D; ++i ) + { + if ( b.upper_right[ i ] < center_[ i ] - radius_ or b.lower_left[ i ] > center_[ i ] + radius_ ) + { + return true; + } + } + return false; +} + +template < int D > +Box< D > +BallMask< D >::get_bbox() const +{ + Box< D > bb( center_, center_ ); + for ( int i = 0; i < D; ++i ) + { + bb.lower_left[ i ] -= radius_; + bb.upper_right[ i ] += radius_; + } + return bb; +} + +template < int D > +Mask< D >* +BallMask< D >::clone() const +{ + return new BallMask( *this ); +} + +template < int D > +DictionaryDatum +BallMask< D >::get_dict() const +{ + DictionaryDatum d( new Dictionary ); + DictionaryDatum maskd( new Dictionary ); + def< DictionaryDatum >( d, get_name(), maskd ); + def< double >( maskd, names::radius, radius_ ); + def< std::vector< double > >( maskd, names::anchor, center_.get_vector() ); + return d; +} + +template < int D > +void +EllipseMask< D >::create_bbox_() +{ + // Currently assumes 3D when constructing the radius vector. This could be + // avoided with more if tests, but the vector is only made once and is not + // big. The construction of the box is done in accordance with the actual + // dimensions. + std::vector< double > radii( 3 ); + if ( azimuth_angle_ == 0.0 and polar_angle_ == 0.0 ) + { + radii[ 0 ] = major_axis_ / 2.0; + radii[ 1 ] = minor_axis_ / 2.0; + radii[ 2 ] = polar_axis_ / 2.0; + } + else + { + // If the ellipse or ellipsoid is tilted, we make the boundary box + // quadratic, with the length of the sides equal to the axis with greatest + // length. This could be more refined. + const double greatest_semi_axis = std::max( major_axis_, polar_axis_ ) / 2.0; + radii[ 0 ] = greatest_semi_axis; + radii[ 1 ] = greatest_semi_axis; + radii[ 2 ] = greatest_semi_axis; + } + + for ( int i = 0; i < D; ++i ) + { + bbox_.lower_left[ i ] = center_[ i ] - radii[ i ]; + bbox_.upper_right[ i ] = center_[ i ] + radii[ i ]; + } +} + +template < int D > +bool +EllipseMask< D >::outside( const Box< D >& b ) const +{ + // Currently only checks if the box is outside the bounding box of + // the ellipse. This could be made more refined. + + const Box< D >& bb = bbox_; + + for ( int i = 0; i < D; ++i ) + { + if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] ) + { + return true; + } + } + return false; +} + +template < int D > +Box< D > +EllipseMask< D >::get_bbox() const +{ + return bbox_; +} + +template < int D > +Mask< D >* +EllipseMask< D >::clone() const +{ + return new EllipseMask( *this ); +} + +template < int D > +DictionaryDatum +EllipseMask< D >::get_dict() const +{ + DictionaryDatum d( new Dictionary ); + DictionaryDatum maskd( new Dictionary ); + def< DictionaryDatum >( d, get_name(), maskd ); + def< double >( maskd, names::major_axis, major_axis_ ); + def< double >( maskd, names::minor_axis, minor_axis_ ); + def< double >( maskd, names::polar_axis, polar_axis_ ); + def< std::vector< double > >( maskd, names::anchor, center_.get_vector() ); + def< double >( maskd, names::azimuth_angle, azimuth_angle_ ); + def< double >( maskd, names::polar_angle, polar_angle_ ); + return d; +} + + +template < int D > +bool +IntersectionMask< D >::inside( const Position< D >& p ) const +{ + return mask1_->inside( p ) and mask2_->inside( p ); +} + +template < int D > +bool +IntersectionMask< D >::inside( const Box< D >& b ) const +{ + return mask1_->inside( b ) and mask2_->inside( b ); +} + +template < int D > +bool +IntersectionMask< D >::outside( const Box< D >& b ) const +{ + return mask1_->outside( b ) or mask2_->outside( b ); +} + +template < int D > +Box< D > +IntersectionMask< D >::get_bbox() const +{ + Box< D > bb = mask1_->get_bbox(); + Box< D > bb2 = mask2_->get_bbox(); + for ( int i = 0; i < D; ++i ) + { + if ( bb2.lower_left[ i ] > bb.lower_left[ i ] ) + { + bb.lower_left[ i ] = bb2.lower_left[ i ]; + } + if ( bb2.upper_right[ i ] < bb.upper_right[ i ] ) + { + bb.upper_right[ i ] = bb2.upper_right[ i ]; + } + } + return bb; +} + +template < int D > +Mask< D >* +IntersectionMask< D >::clone() const +{ + return new IntersectionMask( *this ); +} + +template < int D > +bool +UnionMask< D >::inside( const Position< D >& p ) const +{ + return mask1_->inside( p ) or mask2_->inside( p ); +} + +template < int D > +bool +UnionMask< D >::inside( const Box< D >& b ) const +{ + return mask1_->inside( b ) or mask2_->inside( b ); +} + +template < int D > +bool +UnionMask< D >::outside( const Box< D >& b ) const +{ + return mask1_->outside( b ) and mask2_->outside( b ); +} + +template < int D > +Box< D > +UnionMask< D >::get_bbox() const +{ + Box< D > bb = mask1_->get_bbox(); + Box< D > bb2 = mask2_->get_bbox(); + for ( int i = 0; i < D; ++i ) + { + if ( bb2.lower_left[ i ] < bb.lower_left[ i ] ) + { + bb.lower_left[ i ] = bb2.lower_left[ i ]; + } + if ( bb2.upper_right[ i ] > bb.upper_right[ i ] ) + { + bb.upper_right[ i ] = bb2.upper_right[ i ]; + } + } + return bb; +} + +template < int D > +Mask< D >* +UnionMask< D >::clone() const +{ + return new UnionMask( *this ); +} + +template < int D > +bool +DifferenceMask< D >::inside( const Position< D >& p ) const +{ + return mask1_->inside( p ) and not mask2_->inside( p ); +} + +template < int D > +bool +DifferenceMask< D >::inside( const Box< D >& b ) const +{ + return mask1_->inside( b ) and mask2_->outside( b ); +} + +template < int D > +bool +DifferenceMask< D >::outside( const Box< D >& b ) const +{ + return mask1_->outside( b ) or mask2_->inside( b ); +} + +template < int D > +Box< D > +DifferenceMask< D >::get_bbox() const +{ + return mask1_->get_bbox(); +} + +template < int D > +Mask< D >* +DifferenceMask< D >::clone() const +{ + return new DifferenceMask( *this ); +} + +template < int D > +bool +ConverseMask< D >::inside( const Position< D >& p ) const +{ + return m_->inside( -p ); +} + +template < int D > +bool +ConverseMask< D >::inside( const Box< D >& b ) const +{ + return m_->inside( Box< D >( -b.upper_right, -b.lower_left ) ); +} + +template < int D > +bool +ConverseMask< D >::outside( const Box< D >& b ) const +{ + return m_->outside( Box< D >( -b.upper_right, -b.lower_left ) ); +} + +template < int D > +Box< D > +ConverseMask< D >::get_bbox() const +{ + Box< D > bb = m_->get_bbox(); + return Box< D >( -bb.upper_right, -bb.lower_left ); +} + +template < int D > +Mask< D >* +ConverseMask< D >::clone() const +{ + return new ConverseMask( *this ); +} + +template < int D > +bool +AnchoredMask< D >::inside( const Position< D >& p ) const +{ + return m_->inside( p - anchor_ ); +} + +template < int D > +bool +AnchoredMask< D >::inside( const Box< D >& b ) const +{ + return m_->inside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) ); +} + +template < int D > +bool +AnchoredMask< D >::outside( const Box< D >& b ) const +{ + return m_->outside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) ); +} + +template < int D > +Box< D > +AnchoredMask< D >::get_bbox() const +{ + Box< D > bb = m_->get_bbox(); + return Box< D >( bb.lower_left + anchor_, bb.upper_right + anchor_ ); +} + +template < int D > +Mask< D >* +AnchoredMask< D >::clone() const +{ + return new AnchoredMask( *this ); +} + +template < int D > +DictionaryDatum +AnchoredMask< D >::get_dict() const +{ + DictionaryDatum d = m_->get_dict(); + def< std::vector< double > >( d, names::anchor, anchor_.get_vector() ); + return d; +} + } // namespace nest #endif diff --git a/nestkernel/mask_impl.h b/nestkernel/mask_impl.h deleted file mode 100644 index d62bab2e58..0000000000 --- a/nestkernel/mask_impl.h +++ /dev/null @@ -1,515 +0,0 @@ -/* - * mask_impl.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 MASK_IMPL_H -#define MASK_IMPL_H - -#include "mask.h" - -namespace nest -{ - -template < int D > -AbstractMask* -Mask< D >::intersect_mask( const AbstractMask& other ) const -{ - const Mask* other_d = dynamic_cast< const Mask* >( &other ); - if ( other_d == 0 ) - { - throw BadProperty( "Masks must have same number of dimensions." ); - } - return new IntersectionMask< D >( *this, *other_d ); -} - -template < int D > -AbstractMask* -Mask< D >::union_mask( const AbstractMask& other ) const -{ - const Mask* other_d = dynamic_cast< const Mask* >( &other ); - if ( other_d == 0 ) - { - throw BadProperty( "Masks must have same number of dimensions." ); - } - return new UnionMask< D >( *this, *other_d ); -} - -template < int D > -AbstractMask* -Mask< D >::minus_mask( const AbstractMask& other ) const -{ - const Mask* other_d = dynamic_cast< const Mask* >( &other ); - if ( other_d == 0 ) - { - throw BadProperty( "Masks must have same number of dimensions." ); - } - return new DifferenceMask< D >( *this, *other_d ); -} - -template < int D > -bool -Mask< D >::inside( const std::vector< double >& pt ) const -{ - return inside( Position< D >( pt ) ); -} - -template < int D > -bool -Mask< D >::outside( const Box< D >& b ) const -{ - Box< D > bb = get_bbox(); - for ( int i = 0; i < D; ++i ) - { - if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] ) - { - return true; - } - } - return false; -} - -template < int D > -bool -BoxMask< D >::inside( const Box< D >& b ) const -{ - return ( inside( b.lower_left ) and inside( b.upper_right ) ); -} - -template < int D > -bool -BoxMask< D >::outside( const Box< D >& b ) const -{ - // Note: There could be some inconsistencies with the boundaries. For the - // inside() function we had to add an epsilon because of rounding errors that - // can occur if node IDs are on the boundary if we have rotation. This might lead - // to overlap of the inside and outside functions. None of the tests have - // picked up any problems with this potential overlap as of yet (autumn 2017), - // so we don't know if it is an actual problem. - for ( int i = 0; i < D; ++i ) - { - if ( b.upper_right[ i ] < min_values_[ i ] or b.lower_left[ i ] > max_values_[ i ] ) - { - return true; - } - } - return false; -} - -template < int D > -Box< D > -BoxMask< D >::get_bbox() const -{ - return Box< D >( min_values_, max_values_ ); -} - -template < int D > -Mask< D >* -BoxMask< D >::clone() const -{ - return new BoxMask( *this ); -} - -template < int D > -DictionaryDatum -BoxMask< D >::get_dict() const -{ - DictionaryDatum d( new Dictionary ); - DictionaryDatum maskd( new Dictionary ); - def< DictionaryDatum >( d, get_name(), maskd ); - def< std::vector< double > >( maskd, names::lower_left, lower_left_.get_vector() ); - def< std::vector< double > >( maskd, names::upper_right, upper_right_.get_vector() ); - def< double >( maskd, names::azimuth_angle, azimuth_angle_ ); - def< double >( maskd, names::polar_angle, polar_angle_ ); - return d; -} - -template < int D > -bool -BallMask< D >::inside( const Position< D >& p ) const -{ - // Optimizing by trying to avoid expensive calculations. - double dim_sum = 0; - // First check each dimension - for ( int i = 0; i < D; ++i ) - { - const double di = std::abs( p[ i ] - center_[ i ] ); - if ( di > radius_ ) - { - return false; - } - dim_sum += di; - } - // Next, check if we are inside a diamond (rotated square), which fits inside the ball. - if ( dim_sum <= radius_ ) - { - return true; - } - // Point must be somewhere between the ball mask edge and the diamond edge, - // revert to expensive calculation in this case. - return ( p - center_ ).length() <= radius_; -} - -template < int D > -bool -BallMask< D >::outside( const Box< D >& b ) const -{ - // Currently only checks if the box is outside the bounding box of - // the ball. This could be made more refined. - for ( int i = 0; i < D; ++i ) - { - if ( b.upper_right[ i ] < center_[ i ] - radius_ or b.lower_left[ i ] > center_[ i ] + radius_ ) - { - return true; - } - } - return false; -} - -template < int D > -Box< D > -BallMask< D >::get_bbox() const -{ - Box< D > bb( center_, center_ ); - for ( int i = 0; i < D; ++i ) - { - bb.lower_left[ i ] -= radius_; - bb.upper_right[ i ] += radius_; - } - return bb; -} - -template < int D > -Mask< D >* -BallMask< D >::clone() const -{ - return new BallMask( *this ); -} - -template < int D > -DictionaryDatum -BallMask< D >::get_dict() const -{ - DictionaryDatum d( new Dictionary ); - DictionaryDatum maskd( new Dictionary ); - def< DictionaryDatum >( d, get_name(), maskd ); - def< double >( maskd, names::radius, radius_ ); - def< std::vector< double > >( maskd, names::anchor, center_.get_vector() ); - return d; -} - -template < int D > -void -EllipseMask< D >::create_bbox_() -{ - // Currently assumes 3D when constructing the radius vector. This could be - // avoided with more if tests, but the vector is only made once and is not - // big. The construction of the box is done in accordance with the actual - // dimensions. - std::vector< double > radii( 3 ); - if ( azimuth_angle_ == 0.0 and polar_angle_ == 0.0 ) - { - radii[ 0 ] = major_axis_ / 2.0; - radii[ 1 ] = minor_axis_ / 2.0; - radii[ 2 ] = polar_axis_ / 2.0; - } - else - { - // If the ellipse or ellipsoid is tilted, we make the boundary box - // quadratic, with the length of the sides equal to the axis with greatest - // length. This could be more refined. - const double greatest_semi_axis = std::max( major_axis_, polar_axis_ ) / 2.0; - radii[ 0 ] = greatest_semi_axis; - radii[ 1 ] = greatest_semi_axis; - radii[ 2 ] = greatest_semi_axis; - } - - for ( int i = 0; i < D; ++i ) - { - bbox_.lower_left[ i ] = center_[ i ] - radii[ i ]; - bbox_.upper_right[ i ] = center_[ i ] + radii[ i ]; - } -} - -template < int D > -bool -EllipseMask< D >::outside( const Box< D >& b ) const -{ - // Currently only checks if the box is outside the bounding box of - // the ellipse. This could be made more refined. - - const Box< D >& bb = bbox_; - - for ( int i = 0; i < D; ++i ) - { - if ( b.upper_right[ i ] < bb.lower_left[ i ] or b.lower_left[ i ] > bb.upper_right[ i ] ) - { - return true; - } - } - return false; -} - -template < int D > -Box< D > -EllipseMask< D >::get_bbox() const -{ - return bbox_; -} - -template < int D > -Mask< D >* -EllipseMask< D >::clone() const -{ - return new EllipseMask( *this ); -} - -template < int D > -DictionaryDatum -EllipseMask< D >::get_dict() const -{ - DictionaryDatum d( new Dictionary ); - DictionaryDatum maskd( new Dictionary ); - def< DictionaryDatum >( d, get_name(), maskd ); - def< double >( maskd, names::major_axis, major_axis_ ); - def< double >( maskd, names::minor_axis, minor_axis_ ); - def< double >( maskd, names::polar_axis, polar_axis_ ); - def< std::vector< double > >( maskd, names::anchor, center_.get_vector() ); - def< double >( maskd, names::azimuth_angle, azimuth_angle_ ); - def< double >( maskd, names::polar_angle, polar_angle_ ); - return d; -} - - -template < int D > -bool -IntersectionMask< D >::inside( const Position< D >& p ) const -{ - return mask1_->inside( p ) and mask2_->inside( p ); -} - -template < int D > -bool -IntersectionMask< D >::inside( const Box< D >& b ) const -{ - return mask1_->inside( b ) and mask2_->inside( b ); -} - -template < int D > -bool -IntersectionMask< D >::outside( const Box< D >& b ) const -{ - return mask1_->outside( b ) or mask2_->outside( b ); -} - -template < int D > -Box< D > -IntersectionMask< D >::get_bbox() const -{ - Box< D > bb = mask1_->get_bbox(); - Box< D > bb2 = mask2_->get_bbox(); - for ( int i = 0; i < D; ++i ) - { - if ( bb2.lower_left[ i ] > bb.lower_left[ i ] ) - { - bb.lower_left[ i ] = bb2.lower_left[ i ]; - } - if ( bb2.upper_right[ i ] < bb.upper_right[ i ] ) - { - bb.upper_right[ i ] = bb2.upper_right[ i ]; - } - } - return bb; -} - -template < int D > -Mask< D >* -IntersectionMask< D >::clone() const -{ - return new IntersectionMask( *this ); -} - -template < int D > -bool -UnionMask< D >::inside( const Position< D >& p ) const -{ - return mask1_->inside( p ) or mask2_->inside( p ); -} - -template < int D > -bool -UnionMask< D >::inside( const Box< D >& b ) const -{ - return mask1_->inside( b ) or mask2_->inside( b ); -} - -template < int D > -bool -UnionMask< D >::outside( const Box< D >& b ) const -{ - return mask1_->outside( b ) and mask2_->outside( b ); -} - -template < int D > -Box< D > -UnionMask< D >::get_bbox() const -{ - Box< D > bb = mask1_->get_bbox(); - Box< D > bb2 = mask2_->get_bbox(); - for ( int i = 0; i < D; ++i ) - { - if ( bb2.lower_left[ i ] < bb.lower_left[ i ] ) - { - bb.lower_left[ i ] = bb2.lower_left[ i ]; - } - if ( bb2.upper_right[ i ] > bb.upper_right[ i ] ) - { - bb.upper_right[ i ] = bb2.upper_right[ i ]; - } - } - return bb; -} - -template < int D > -Mask< D >* -UnionMask< D >::clone() const -{ - return new UnionMask( *this ); -} - -template < int D > -bool -DifferenceMask< D >::inside( const Position< D >& p ) const -{ - return mask1_->inside( p ) and not mask2_->inside( p ); -} - -template < int D > -bool -DifferenceMask< D >::inside( const Box< D >& b ) const -{ - return mask1_->inside( b ) and mask2_->outside( b ); -} - -template < int D > -bool -DifferenceMask< D >::outside( const Box< D >& b ) const -{ - return mask1_->outside( b ) or mask2_->inside( b ); -} - -template < int D > -Box< D > -DifferenceMask< D >::get_bbox() const -{ - return mask1_->get_bbox(); -} - -template < int D > -Mask< D >* -DifferenceMask< D >::clone() const -{ - return new DifferenceMask( *this ); -} - -template < int D > -bool -ConverseMask< D >::inside( const Position< D >& p ) const -{ - return m_->inside( -p ); -} - -template < int D > -bool -ConverseMask< D >::inside( const Box< D >& b ) const -{ - return m_->inside( Box< D >( -b.upper_right, -b.lower_left ) ); -} - -template < int D > -bool -ConverseMask< D >::outside( const Box< D >& b ) const -{ - return m_->outside( Box< D >( -b.upper_right, -b.lower_left ) ); -} - -template < int D > -Box< D > -ConverseMask< D >::get_bbox() const -{ - Box< D > bb = m_->get_bbox(); - return Box< D >( -bb.upper_right, -bb.lower_left ); -} - -template < int D > -Mask< D >* -ConverseMask< D >::clone() const -{ - return new ConverseMask( *this ); -} - -template < int D > -bool -AnchoredMask< D >::inside( const Position< D >& p ) const -{ - return m_->inside( p - anchor_ ); -} - -template < int D > -bool -AnchoredMask< D >::inside( const Box< D >& b ) const -{ - return m_->inside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) ); -} - -template < int D > -bool -AnchoredMask< D >::outside( const Box< D >& b ) const -{ - return m_->outside( Box< D >( b.lower_left - anchor_, b.upper_right - anchor_ ) ); -} - -template < int D > -Box< D > -AnchoredMask< D >::get_bbox() const -{ - Box< D > bb = m_->get_bbox(); - return Box< D >( bb.lower_left + anchor_, bb.upper_right + anchor_ ); -} - -template < int D > -Mask< D >* -AnchoredMask< D >::clone() const -{ - return new AnchoredMask( *this ); -} - -template < int D > -DictionaryDatum -AnchoredMask< D >::get_dict() const -{ - DictionaryDatum d = m_->get_dict(); - def< std::vector< double > >( d, names::anchor, anchor_.get_vector() ); - return d; -} - -} // namespace nest - -#endif diff --git a/nestkernel/model.cpp b/nestkernel/model.cpp index 08d2a342a3..9779816cc5 100644 --- a/nestkernel/model.cpp +++ b/nestkernel/model.cpp @@ -31,6 +31,7 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" +#include "model_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/model_manager.cpp b/nestkernel/model_manager.cpp index a656285f13..fc79cc56e4 100644 --- a/nestkernel/model_manager.cpp +++ b/nestkernel/model_manager.cpp @@ -31,12 +31,9 @@ #include "compose.hpp" // Includes from nestkernel: -#include "connector_model_impl.h" -#include "genericmodel_impl.h" +#include "connection_manager.h" #include "kernel_manager.h" -#include "model_manager_impl.h" #include "proxynode.h" -#include "vp_manager_impl.h" // Includes from models: #include "models.h" diff --git a/nestkernel/model_manager.h b/nestkernel/model_manager.h index 924535a780..41b636715d 100644 --- a/nestkernel/model_manager.h +++ b/nestkernel/model_manager.h @@ -27,18 +27,23 @@ #include // Includes from nestkernel: -#include "connector_model.h" +#include "connection_label.h" +#include "connection_manager.h" +#include "connector_model_impl.h" #include "genericmodel.h" +#include "kernel_manager.h" +#include "logging_manager.h" #include "manager_interface.h" #include "model.h" -#include "nest.h" +#include "modelrange_manager.h" #include "nest_time.h" -#include "nest_timeconverter.h" #include "nest_types.h" #include "node.h" +#include "target_identifier.h" + +// Includes from libnestutil: +#include "compose.hpp" -// Includes from sli: -#include "dictutils.h" namespace nest { @@ -326,6 +331,88 @@ ModelManager::get_secondary_event_prototype( const synindex syn_id, const size_t return *get_connection_model( syn_id, tid ).get_secondary_event(); } +template < class ModelT > +size_t +ModelManager::register_node_model( const Name& name, std::string deprecation_info ) +{ + if ( modeldict_->known( name ) ) + { + std::string msg = String::compose( "A model called '%1' already exists. Please choose a different name!", name ); + throw NamingConflict( msg ); + } + + Model* model = new GenericModel< ModelT >( name.toString(), deprecation_info ); + return register_node_model_( model ); +} + +template < template < typename targetidentifierT > class ConnectionT > +void +ModelManager::register_connection_model( const std::string& name ) +{ + // Required to check which variants to create + ConnectorModel const* const dummy_model = + new GenericConnectorModel< ConnectionT< TargetIdentifierPtrRport > >( "dummy" ); + + register_specific_connection_model_< ConnectionT< TargetIdentifierPtrRport > >( name ); + if ( dummy_model->has_property( ConnectionModelProperties::SUPPORTS_HPC ) ) + { + register_specific_connection_model_< ConnectionT< TargetIdentifierIndex > >( name + "_hpc" ); + } + if ( dummy_model->has_property( ConnectionModelProperties::SUPPORTS_LBL ) ) + { + register_specific_connection_model_< ConnectionLabel< ConnectionT< TargetIdentifierPtrRport > > >( name + "_lbl" ); + } + + delete dummy_model; +} + +template < typename CompleteConnectionT > +void +ModelManager::register_specific_connection_model_( const std::string& name ) +{ + kernel().vp_manager.assert_single_threaded(); + + if ( synapsedict_->known( name ) ) + { + std::string msg = + String::compose( "A synapse type called '%1' already exists.\nPlease choose a different name!", name ); + throw NamingConflict( msg ); + } + + const auto new_syn_id = get_num_connection_models(); + if ( new_syn_id >= invalid_synindex ) + { + const std::string msg = String::compose( + "CopyModel cannot generate another synapse. Maximal synapse model count of %1 exceeded.", MAX_SYN_ID ); + LOG( M_ERROR, "ModelManager::copy_connection_model_", msg ); + throw KernelException( "Synapse model count exceeded" ); + } + + synapsedict_->insert( name, new_syn_id ); + +#pragma omp parallel + { + ConnectorModel* conn_model = new GenericConnectorModel< CompleteConnectionT >( name ); + conn_model->set_syn_id( new_syn_id ); + if ( not conn_model->has_property( ConnectionModelProperties::IS_PRIMARY ) ) + { + conn_model->get_secondary_event()->add_syn_id( new_syn_id ); + } + connection_models_.at( kernel().vp_manager.get_thread_id() ).push_back( conn_model ); + kernel().connection_manager.resize_connections(); + } // end of parallel section +} + +inline Node* +ModelManager::get_proxy_node( size_t tid, size_t node_id ) +{ + const int model_id = kernel().modelrange_manager.get_model_id( node_id ); + Node* proxy = proxy_nodes_[ tid ].at( model_id ); + proxy->set_node_id_( node_id ); + proxy->set_vp( kernel().vp_manager.node_id_to_vp( node_id ) ); + return proxy; +} + } // namespace nest #endif /* MODEL_MANAGER_H */ diff --git a/nestkernel/model_manager_impl.h b/nestkernel/model_manager_impl.h index d9e8d8e6c7..e69de29bb2 100644 --- a/nestkernel/model_manager_impl.h +++ b/nestkernel/model_manager_impl.h @@ -1,126 +0,0 @@ -/* - * model_manager_impl.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 MODEL_MANAGER_IMPL_H -#define MODEL_MANAGER_IMPL_H - -#include "model_manager.h" - -// Includes from libnestutil: -#include "compose.hpp" -#include "string_utils.h" - -// Includes from nestkernel: -#include "connection_label.h" -#include "kernel_manager.h" -#include "nest.h" -#include "target_identifier.h" - - -namespace nest -{ - -template < class ModelT > -size_t -ModelManager::register_node_model( const Name& name, std::string deprecation_info ) -{ - if ( modeldict_->known( name ) ) - { - std::string msg = String::compose( "A model called '%1' already exists. Please choose a different name!", name ); - throw NamingConflict( msg ); - } - - Model* model = new GenericModel< ModelT >( name.toString(), deprecation_info ); - return register_node_model_( model ); -} - -template < template < typename targetidentifierT > class ConnectionT > -void -ModelManager::register_connection_model( const std::string& name ) -{ - // Required to check which variants to create - ConnectorModel const* const dummy_model = - new GenericConnectorModel< ConnectionT< TargetIdentifierPtrRport > >( "dummy" ); - - register_specific_connection_model_< ConnectionT< TargetIdentifierPtrRport > >( name ); - if ( dummy_model->has_property( ConnectionModelProperties::SUPPORTS_HPC ) ) - { - register_specific_connection_model_< ConnectionT< TargetIdentifierIndex > >( name + "_hpc" ); - } - if ( dummy_model->has_property( ConnectionModelProperties::SUPPORTS_LBL ) ) - { - register_specific_connection_model_< ConnectionLabel< ConnectionT< TargetIdentifierPtrRport > > >( name + "_lbl" ); - } - - delete dummy_model; -} - -template < typename CompleteConnectionT > -void -ModelManager::register_specific_connection_model_( const std::string& name ) -{ - kernel().vp_manager.assert_single_threaded(); - - if ( synapsedict_->known( name ) ) - { - std::string msg = - String::compose( "A synapse type called '%1' already exists.\nPlease choose a different name!", name ); - throw NamingConflict( msg ); - } - - const auto new_syn_id = get_num_connection_models(); - if ( new_syn_id >= invalid_synindex ) - { - const std::string msg = String::compose( - "CopyModel cannot generate another synapse. Maximal synapse model count of %1 exceeded.", MAX_SYN_ID ); - LOG( M_ERROR, "ModelManager::copy_connection_model_", msg ); - throw KernelException( "Synapse model count exceeded" ); - } - - synapsedict_->insert( name, new_syn_id ); - -#pragma omp parallel - { - ConnectorModel* conn_model = new GenericConnectorModel< CompleteConnectionT >( name ); - conn_model->set_syn_id( new_syn_id ); - if ( not conn_model->has_property( ConnectionModelProperties::IS_PRIMARY ) ) - { - conn_model->get_secondary_event()->add_syn_id( new_syn_id ); - } - connection_models_.at( kernel().vp_manager.get_thread_id() ).push_back( conn_model ); - kernel().connection_manager.resize_connections(); - } // end of parallel section -} - -inline Node* -ModelManager::get_proxy_node( size_t tid, size_t node_id ) -{ - const int model_id = kernel().modelrange_manager.get_model_id( node_id ); - Node* proxy = proxy_nodes_[ tid ].at( model_id ); - proxy->set_node_id_( node_id ); - proxy->set_vp( kernel().vp_manager.node_id_to_vp( node_id ) ); - return proxy; -} - -} // namespace nest - -#endif /* #ifndef MODEL_MANAGER_IMPL_H */ diff --git a/nestkernel/modelrange_manager.cpp b/nestkernel/modelrange_manager.cpp index 9b33323a87..29b2ac09b3 100644 --- a/nestkernel/modelrange_manager.cpp +++ b/nestkernel/modelrange_manager.cpp @@ -28,6 +28,7 @@ // Includes from nestkernel: #include "kernel_manager.h" #include "model.h" +#include "model_manager.h" namespace nest diff --git a/nestkernel/mpi_manager.cpp b/nestkernel/mpi_manager.cpp index 5da18cc3ac..48b2aab7cd 100644 --- a/nestkernel/mpi_manager.cpp +++ b/nestkernel/mpi_manager.cpp @@ -26,16 +26,23 @@ #include // Includes from libnestutil: -#include "stopwatch_impl.h" // Includes from nestkernel: #include "kernel_manager.h" -#include "mpi_manager_impl.h" #include "nest_types.h" +#include "logging.h" +#include "logging_manager.h" +#include "music_manager.h" +#include "nest_names.h" +#include "stopwatch.h" + // Includes from sli: #include "dictutils.h" +namespace nest +{ + #ifdef HAVE_MPI template <> @@ -1110,3 +1117,4 @@ nest::MPIManager::communicate_recv_counts_secondary_events() } #endif /* #ifdef HAVE_MPI */ +} // namespace nest diff --git a/nestkernel/mpi_manager.h b/nestkernel/mpi_manager.h index a8f4fcea7e..f70bb09623 100644 --- a/nestkernel/mpi_manager.h +++ b/nestkernel/mpi_manager.h @@ -35,16 +35,15 @@ // C++ includes: #include #include -#include #include #include #include // Includes from libnestutil: #include "manager_interface.h" -#include "stopwatch.h" // Includes from nestkernel: +#include "kernel_manager.h" #include "nest_types.h" #include "spike_data.h" #include "target_data.h" @@ -104,11 +103,6 @@ class MPIManager : public ManagerInterface */ size_t get_process_id_of_vp( const size_t vp ) const; - /* - * Return the process id of the node with the specified node ID. - */ - size_t get_process_id_of_node_id( const size_t node_id ) const; - /** * Finalize MPI communication (needs to be separate from MPIManager::finalize * when compiled with MUSIC since spikes can arrive and handlers called here) @@ -762,6 +756,48 @@ MPIManager::communicate_off_grid_spike_data_Alltoall( std::vector< D >& send_buf communicate_Alltoall( send_buffer, recv_buffer, send_recv_count_off_grid_spike_data_in_int_per_rank ); } + +inline size_t +nest::MPIManager::get_process_id_of_vp( const size_t vp ) const +{ + return vp % num_processes_; +} + +#ifdef HAVE_MPI + +// Variable to hold the MPI communicator to use. +#ifdef HAVE_MUSIC +extern MPI::Intracomm comm; +#else /* #ifdef HAVE_MUSIC */ +extern MPI_Comm comm; +#endif /* #ifdef HAVE_MUSIC */ + +template < typename T > +struct MPI_Type +{ + static MPI_Datatype type; +}; + +template < typename T > +void +nest::MPIManager::communicate_Allgatherv( std::vector< T >& send_buffer, + std::vector< T >& recv_buffer, + std::vector< int >& displacements, + std::vector< int >& recv_counts ) +{ + // attempt Allgather + MPI_Allgatherv( &( *send_buffer.begin() ), + send_buffer.size(), + MPI_Type< T >::type, + &recv_buffer[ 0 ], + &recv_counts[ 0 ], + &displacements[ 0 ], + MPI_Type< T >::type, + comm ); +} + +#endif /* HAVE_MPI */ + } #endif /* MPI_MANAGER_H */ diff --git a/nestkernel/mpi_manager_impl.h b/nestkernel/mpi_manager_impl.h deleted file mode 100644 index 1f596adc3c..0000000000 --- a/nestkernel/mpi_manager_impl.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * mpi_manager_impl.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 MPI_MANAGER_IMPL_H -#define MPI_MANAGER_IMPL_H - -#include "config.h" - -#ifdef HAVE_MPI -// C includes: -#include -#endif /* #ifdef HAVE_MPI */ - -#include "mpi_manager.h" - -// Includes from nestkernel: -#include "kernel_manager.h" - -inline size_t -nest::MPIManager::get_process_id_of_vp( const size_t vp ) const -{ - return vp % num_processes_; -} - -#ifdef HAVE_MPI - -// Variable to hold the MPI communicator to use. -#ifdef HAVE_MUSIC -extern MPI::Intracomm comm; -#else /* #ifdef HAVE_MUSIC */ -extern MPI_Comm comm; -#endif /* #ifdef HAVE_MUSIC */ - -template < typename T > -struct MPI_Type -{ - static MPI_Datatype type; -}; - -template < typename T > -void -nest::MPIManager::communicate_Allgatherv( std::vector< T >& send_buffer, - std::vector< T >& recv_buffer, - std::vector< int >& displacements, - std::vector< int >& recv_counts ) -{ - // attempt Allgather - MPI_Allgatherv( &( *send_buffer.begin() ), - send_buffer.size(), - MPI_Type< T >::type, - &recv_buffer[ 0 ], - &recv_counts[ 0 ], - &displacements[ 0 ], - MPI_Type< T >::type, - comm ); -} - -inline size_t -nest::MPIManager::get_process_id_of_node_id( const size_t node_id ) const -{ - return node_id % kernel().vp_manager.get_num_virtual_processes() % num_processes_; -} - -#else // HAVE_MPI - - -inline size_t -nest::MPIManager::get_process_id_of_node_id( const size_t ) const -{ - return 0; -} - -#endif /* HAVE_MPI */ - -#endif /* MPI_MANAGER_IMPL_H */ diff --git a/nestkernel/music_event_handler.cpp b/nestkernel/music_event_handler.cpp index 9f0a7dc616..1407adea8a 100644 --- a/nestkernel/music_event_handler.cpp +++ b/nestkernel/music_event_handler.cpp @@ -31,6 +31,8 @@ // Includes from nestkernel: #include "event.h" #include "kernel_manager.h" +#include "logging_manager.h" +#include "music_manager.h" #include "nest_types.h" namespace nest diff --git a/nestkernel/music_manager.cpp b/nestkernel/music_manager.cpp index ec237eca7d..deedb47277 100644 --- a/nestkernel/music_manager.cpp +++ b/nestkernel/music_manager.cpp @@ -30,7 +30,10 @@ #endif // Includes from nestkernel: +#include "compose.hpp" #include "kernel_manager.h" +#include "logging.h" +#include "logging_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/music_rate_in_handler.cpp b/nestkernel/music_rate_in_handler.cpp index 0ebfe55f41..55a4089858 100644 --- a/nestkernel/music_rate_in_handler.cpp +++ b/nestkernel/music_rate_in_handler.cpp @@ -29,8 +29,10 @@ #include "logging.h" // Includes from nestkernel: -#include "event.h" +#include "connection_manager.h" #include "kernel_manager.h" +#include "logging_manager.h" +#include "music_manager.h" #include "nest_types.h" namespace nest diff --git a/nestkernel/nest.cpp b/nestkernel/nest.cpp index 2add49bcb6..d050d932bb 100644 --- a/nestkernel/nest.cpp +++ b/nestkernel/nest.cpp @@ -26,10 +26,17 @@ #include // Includes from nestkernel: +#include "connection_manager.h" #include "exceptions.h" +#include "io_manager.h" #include "kernel_manager.h" -#include "mpi_manager_impl.h" +#include "logging_manager.h" +#include "model_manager.h" +#include "node_manager.h" #include "parameter.h" +#include "random_manager.h" +#include "simulation_manager.h" +#include "sp_manager.h" // Includes from sli: #include "sliexceptions.h" diff --git a/nestkernel/nest.h b/nestkernel/nest.h index e49c7dcb5e..5bd652200b 100644 --- a/nestkernel/nest.h +++ b/nestkernel/nest.h @@ -23,17 +23,13 @@ #ifndef NEST_H #define NEST_H -// C++ includes: -#include - // Includes from libnestutil: -#include "enum_bitfield.h" #include "logging.h" // Includes from nestkernel: +#include "kernel_manager.h" +#include "model_manager.h" #include "nest_datums.h" -#include "nest_time.h" -#include "nest_types.h" // Includes from sli: #include "arraydatum.h" @@ -190,6 +186,20 @@ std::vector< double > apply( const ParameterDatum& param, const DictionaryDatum& Datum* node_collection_array_index( const Datum* datum, const long* array, unsigned long n ); Datum* node_collection_array_index( const Datum* datum, const bool* array, unsigned long n ); +template < template < typename > class ConnectorModelT > +void +register_connection_model( const std::string& name ) +{ + kernel().model_manager.register_connection_model< ConnectorModelT >( name ); +} + +template < typename NodeModelT > +void +register_node_model( const std::string& name, std::string deprecation_info ) +{ + kernel().model_manager.register_node_model< NodeModelT >( name, deprecation_info ); +} + } diff --git a/nestkernel/nest_extension_interface.h b/nestkernel/nest_extension_interface.h index ff4d519a21..624317dbe1 100644 --- a/nestkernel/nest_extension_interface.h +++ b/nestkernel/nest_extension_interface.h @@ -26,19 +26,12 @@ // Includes from nestkernel; placed here so module developer does not need to // include them manually #include "config.h" -#include "connection_manager_impl.h" -#include "connector_model_impl.h" #include "exceptions.h" #include "genericmodel.h" -#include "genericmodel_impl.h" -#include "io_manager_impl.h" #include "kernel_manager.h" #include "model.h" -#include "model_manager_impl.h" #include "nest.h" -#include "nest_impl.h" #include "nestmodule.h" -#include "sp_manager_impl.h" #include "target_identifier.h" // C++ includes diff --git a/nestkernel/nestmodule.cpp b/nestkernel/nestmodule.cpp index 77e8d3ae7d..7a7f3449ce 100644 --- a/nestkernel/nestmodule.cpp +++ b/nestkernel/nestmodule.cpp @@ -29,23 +29,18 @@ #include "logging.h" // Includes from nestkernel: -#include "conn_builder.h" -#include "connection_creator_impl.h" #include "free_layer.h" -#include "genericmodel.h" -#include "grid_layer.h" #include "grid_mask.h" #include "kernel_manager.h" -#include "layer.h" #include "layer_impl.h" +#include "logging_manager.h" #include "mask.h" -#include "mask_impl.h" -#include "model_manager_impl.h" +#include "module_manager.h" +#include "music_manager.h" #include "nest.h" #include "nest_datums.h" -#include "nest_types.h" -#include "node.h" #include "parameter.h" +#include "sp_manager.h" #include "spatial.h" // Includes from sli: diff --git a/nestkernel/node.cpp b/nestkernel/node.cpp index 6f54cc1075..602c6431a9 100644 --- a/nestkernel/node.cpp +++ b/nestkernel/node.cpp @@ -29,6 +29,8 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" +#include "model_manager.h" +#include "node_manager.h" // Includes from sli: #include "arraydatum.h" diff --git a/nestkernel/node.h b/nestkernel/node.h index 5c41113f43..a6c4504747 100644 --- a/nestkernel/node.h +++ b/nestkernel/node.h @@ -26,9 +26,7 @@ // C++ includes: #include #include -#include #include -#include #include // Includes from nestkernel: diff --git a/nestkernel/node_collection.cpp b/nestkernel/node_collection.cpp index b4323921f4..57a75c908b 100644 --- a/nestkernel/node_collection.cpp +++ b/nestkernel/node_collection.cpp @@ -27,14 +27,14 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "mpi_manager_impl.h" +#include "model_manager.h" +#include "modelrange_manager.h" #include "node.h" -#include "vp_manager_impl.h" // C++ includes: +#include "numeric" // accumulate #include // copy #include // lcm -#include // accumulate namespace nest diff --git a/nestkernel/node_manager.cpp b/nestkernel/node_manager.cpp index ca5f28ed98..1de01dba85 100644 --- a/nestkernel/node_manager.cpp +++ b/nestkernel/node_manager.cpp @@ -31,13 +31,15 @@ #include "logging.h" // Includes from nestkernel: +#include "connection_manager.h" +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "logging_manager.h" #include "model.h" -#include "model_manager_impl.h" +#include "model_manager.h" +#include "modelrange_manager.h" #include "node.h" -#include "secondary_event_impl.h" #include "vp_manager.h" -#include "vp_manager_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/ntree.h b/nestkernel/ntree.h index 256f16deec..14e38df718 100644 --- a/nestkernel/ntree.h +++ b/nestkernel/ntree.h @@ -486,6 +486,501 @@ Ntree< D, T, max_capacity, max_depth >::insert( iterator, const std::pair< Posit return insert( val.first, val.second ); } +template < int D, class T, int max_capacity, int max_depth > +Ntree< D, T, max_capacity, max_depth >::iterator::iterator( Ntree& q ) + : ntree_( &q ) + , top_( &q ) + , node_( 0 ) +{ + // First leaf + while ( not ntree_->is_leaf() ) + { + ntree_ = ntree_->children_[ 0 ]; + } + // Find the first non-empty leaf + while ( ntree_->nodes_.empty() ) + { + + next_leaf_(); + if ( ntree_ == 0 ) + { + break; + } + } +} + +template < int D, class T, int max_capacity, int max_depth > +typename Ntree< D, T, max_capacity, max_depth >::iterator& +Ntree< D, T, max_capacity, max_depth >::iterator::operator++() +{ + node_++; + + while ( node_ >= ntree_->nodes_.size() ) + { + + next_leaf_(); + + node_ = 0; + if ( ntree_ == 0 ) + { + break; + } + } + + return *this; +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::iterator::next_leaf_() +{ + + // If we are on the last subntree, move up + while ( ntree_ and ( ntree_ != top_ ) and ntree_->my_subquad_ == N - 1 ) + { + ntree_ = ntree_->parent_; + } + + // Since we stop at the top, this should never happen! + assert( ntree_ != 0 ); + + // If we have reached the top, mark as invalid and return + if ( ntree_ == top_ ) + { + ntree_ = 0; + return; + } + + // Move to next sibling + ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; + + // Move down if this is not a leaf. + while ( not ntree_->is_leaf() ) + { + ntree_ = ntree_->children_[ 0 ]; + } +} + +// Proper mod which returns non-negative numbers +static inline double +mod( double x, double p ) +{ + x = std::fmod( x, p ); + if ( x < 0 ) + { + x += p; + } + return x; +} + +template < int D, class T, int max_capacity, int max_depth > +Ntree< D, T, max_capacity, max_depth >::masked_iterator::masked_iterator( Ntree< D, T, max_capacity, max_depth >& q, + const Mask< D >& mask, + const Position< D >& anchor ) + : ntree_( &q ) + , top_( &q ) + , allin_top_( 0 ) + , node_( 0 ) + , mask_( &mask ) + , anchor_( anchor ) + , anchors_() + , current_anchor_( 0 ) +{ + if ( ntree_->periodic_.any() ) + { + Box< D > mask_bb = mask_->get_bbox(); + + // Move lower left corner of mask into main image of layer + for ( int i = 0; i < D; ++i ) + { + if ( ntree_->periodic_[ i ] ) + { + anchor_[ i ] = + nest::mod( anchor_[ i ] + mask_bb.lower_left[ i ] - ntree_->lower_left_[ i ], ntree_->extent_[ i ] ) + - mask_bb.lower_left[ i ] + ntree_->lower_left_[ i ]; + } + } + anchors_.push_back( anchor_ ); + + // Add extra anchors for each dimension where this is needed + // (Assumes that the mask is not wider than the layer) + for ( int i = 0; i < D; ++i ) + { + if ( ntree_->periodic_[ i ] ) + { + int n = anchors_.size(); + if ( ( anchor_[ i ] + mask_bb.upper_right[ i ] - ntree_->lower_left_[ i ] ) > ntree_->extent_[ i ] ) + { + for ( int j = 0; j < n; ++j ) + { + Position< D > p = anchors_[ j ]; + p[ i ] -= ntree_->extent_[ i ]; + anchors_.push_back( p ); + } + } + } + } + } + + init_(); +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::masked_iterator::init_() +{ + node_ = 0; + allin_top_ = 0; + ntree_ = top_; + + if ( mask_->outside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) + { + + next_anchor_(); + } + else + { + + if ( mask_->inside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) + { + first_leaf_inside_(); + } + else + { + first_leaf_(); + } + + if ( ntree_->nodes_.empty() or ( not mask_->inside( ntree_->nodes_[ node_ ].first - anchor_ ) ) ) + { + ++( *this ); + } + } +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::masked_iterator::next_anchor_() +{ + ++current_anchor_; + if ( current_anchor_ >= anchors_.size() ) + { + // Done. Mark as invalid. + ntree_ = 0; + node_ = 0; + } + else + { + anchor_ = anchors_[ current_anchor_ ]; + init_(); + } +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::masked_iterator::next_leaf_() +{ + + // There are two states: the initial state, and "all in". In the + // all in state, we are in a subtree which is completely inside + // the mask. The allin_top_ is the top of this subtree. When + // exiting the subtree, the state changes to the initial + // state. In the initial state, we must check each quadrant to + // see if it is completely inside or outside the mask. If inside, + // we go all in. If outside, we move on to the next leaf. If + // neither, keep going until we find a leaf. Upon exiting from + // this function, we are either done (ntree_==0), or on a leaf + // node which at least intersects with the mask. If allin_top_!=0, + // the leaf is completely inside the mask. + + if ( allin_top_ ) + { + // state: all in + + // If we are on the last subtree, move up + while ( ntree_ and ( ntree_ != allin_top_ ) and ntree_->my_subquad_ == N - 1 ) + { + ntree_ = ntree_->parent_; + } + + // Since we stop at the top, this should never happen! + assert( ntree_ != 0 ); + + // If we reached the allin_top_, we are no longer all in. + if ( ntree_ != allin_top_ ) + { + + // Move to next sibling + ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; + + // Move down if this is not a leaf. + while ( not ntree_->is_leaf() ) + { + ntree_ = ntree_->children_[ 0 ]; + } + return; + } + + allin_top_ = 0; + // Will continue as not all in. + } + + // state: Not all in + + do + { + + // If we are on the last subtree, move up + while ( ntree_ and ( ntree_ != top_ ) and ntree_->my_subquad_ == N - 1 ) + { + ntree_ = ntree_->parent_; + } + + // Since we stop at the top, this should never happen! + assert( ntree_ != 0 ); + + // If we have reached the top, mark as invalid and return + if ( ntree_ == top_ ) + { + return next_anchor_(); + } + + // Move to next sibling + ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; + // Create anchored position in two steps to avoid creating a new Position object. + anchored_position_ = ntree_->lower_left_; + anchored_position_ -= anchor_; + + if ( mask_->inside( Box< D >( anchored_position_, anchored_position_ + ntree_->extent_ ) ) ) + { + return first_leaf_inside_(); + } + + } while ( mask_->outside( Box< D >( anchored_position_, anchored_position_ + ntree_->extent_ ) ) ); + + return first_leaf_(); +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::masked_iterator::first_leaf_() +{ + while ( not ntree_->is_leaf() ) + { + + ntree_ = ntree_->children_[ 0 ]; + + if ( mask_->inside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) + { + return first_leaf_inside_(); + } + + if ( mask_->outside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) + { + return next_leaf_(); + } + } +} + + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::masked_iterator::first_leaf_inside_() +{ + + allin_top_ = ntree_; + + while ( not ntree_->is_leaf() ) + { + ntree_ = ntree_->children_[ 0 ]; + } +} + +template < int D, class T, int max_capacity, int max_depth > +typename Ntree< D, T, max_capacity, max_depth >::masked_iterator& +Ntree< D, T, max_capacity, max_depth >::masked_iterator::operator++() +{ + ++node_; + + if ( allin_top_ == 0 ) + { + while ( + ( node_ < ntree_->nodes_.size() ) and ( not anchored_position_inside_mask( ntree_->nodes_[ node_ ].first ) ) ) + { + ++node_; + } + } + + while ( node_ >= ntree_->nodes_.size() ) + { + next_leaf_(); + + node_ = 0; + if ( ntree_ == 0 ) + { + break; + } + + if ( allin_top_ == 0 ) + { + while ( + ( node_ < ntree_->nodes_.size() ) and ( not anchored_position_inside_mask( ntree_->nodes_[ node_ ].first ) ) ) + { + ++node_; + } + } + } + + return *this; +} + +template < int D, class T, int max_capacity, int max_depth > +int +Ntree< D, T, max_capacity, max_depth >::subquad_( const Position< D >& pos ) +{ + int r = 0; + for ( int i = 0; i < D; ++i ) + { + // Comparing against an epsilon value in case there are round-off errors. + // Using a negative epsilon value because the round-off error may go both ways + // and the difference we check against may therefore be +/- 10^-16. + const bool in_left_half = + ( ( lower_left_[ i ] + extent_[ i ] / 2 ) - pos[ i ] ) > -std::numeric_limits< double >::epsilon(); + r += ( 1 << i ) * ( in_left_half ? 0 : 1 ); + } + + return r; +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::append_nodes_( std::vector< std::pair< Position< D >, T > >& v ) +{ + if ( leaf_ ) + { + std::copy( nodes_.begin(), nodes_.end(), std::back_inserter( v ) ); + } + else + { + for ( int i = 0; i < N; ++i ) + { + children_[ i ]->append_nodes_( v ); + } + } +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::append_nodes_( std::vector< std::pair< Position< D >, T > >& v, + const Mask< D >& mask, + const Position< D >& anchor ) +{ + if ( mask.outside( Box< D >( lower_left_ - anchor, lower_left_ - anchor + extent_ ) ) ) + { + return; + } + if ( mask.inside( Box< D >( lower_left_ - anchor, lower_left_ - anchor + extent_ ) ) ) + { + return append_nodes_( v ); + } + if ( leaf_ ) + { + + for ( typename std::vector< std::pair< Position< D >, T > >::iterator i = nodes_.begin(); i != nodes_.end(); ++i ) + { + if ( mask.inside( i->first - anchor ) ) + { + v.push_back( *i ); + } + } + } + else + { + for ( int i = 0; i < N; ++i ) + { + children_[ i ]->append_nodes_( v, mask, anchor ); + } + } +} + +template < int D, class T, int max_capacity, int max_depth > +typename Ntree< D, T, max_capacity, max_depth >::iterator +Ntree< D, T, max_capacity, max_depth >::insert( Position< D > pos, const T& node ) +{ + if ( periodic_.any() ) + { + // Map position into standard range when using periodic b.c. Only necessary when + // inserting positions during source driven connect when target has periodic b.c. + // May be inefficient. + for ( int i = 0; i < D; ++i ) + { + if ( periodic_[ i ] ) + { + pos[ i ] = lower_left_[ i ] + std::fmod( pos[ i ] - lower_left_[ i ], extent_[ i ] ); + if ( pos[ i ] < lower_left_[ i ] ) + { + pos[ i ] += extent_[ i ]; + } + } + } + } + + if ( leaf_ and ( nodes_.size() >= max_capacity ) and my_depth_ < max_depth ) + { + split_(); + } + if ( leaf_ ) + { + + for ( int i = 0; i < D; ++i ) + { + // Comparing against an epsilon value in case there are round-off errors. + // Using a negative epsilon value because the round-off error may go both ways + // and the difference we check against may therefore be +/- 10^-16. + assert( ( pos - lower_left_ )[ i ] > -std::numeric_limits< double >::epsilon() + and ( lower_left_ + extent_ - pos )[ i ] > -std::numeric_limits< double >::epsilon() ); + } + + nodes_.push_back( std::pair< Position< D >, T >( pos, node ) ); + + return iterator( *this, nodes_.size() - 1 ); + } + else + { + + return children_[ subquad_( pos ) ]->insert( pos, node ); + } +} + +template < int D, class T, int max_capacity, int max_depth > +void +Ntree< D, T, max_capacity, max_depth >::split_() +{ + assert( leaf_ ); + + for ( int j = 0; j < N; ++j ) + { + Position< D > lower_left = lower_left_; + for ( int i = 0; i < D; ++i ) + { + if ( j & ( 1 << i ) ) + { + lower_left[ i ] += extent_[ i ] * 0.5; + } + } + + children_[ j ] = new Ntree< D, T, max_capacity, max_depth >( lower_left, extent_ * 0.5, 0, this, j ); + } + + for ( typename std::vector< std::pair< Position< D >, T > >::iterator i = nodes_.begin(); i != nodes_.end(); ++i ) + { + children_[ subquad_( i->first ) ]->insert( i->first, i->second ); + } + + nodes_.clear(); + + leaf_ = false; +} + } // namespace nest #endif diff --git a/nestkernel/ntree_impl.h b/nestkernel/ntree_impl.h deleted file mode 100644 index a478097df9..0000000000 --- a/nestkernel/ntree_impl.h +++ /dev/null @@ -1,532 +0,0 @@ -/* - * ntree_impl.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 NTREE_IMPL_H -#define NTREE_IMPL_H - -#include - -#include "ntree.h" - -// Includes from spatial: -#include "mask.h" - -namespace nest -{ - -template < int D, class T, int max_capacity, int max_depth > -Ntree< D, T, max_capacity, max_depth >::iterator::iterator( Ntree& q ) - : ntree_( &q ) - , top_( &q ) - , node_( 0 ) -{ - // First leaf - while ( not ntree_->is_leaf() ) - { - ntree_ = ntree_->children_[ 0 ]; - } - // Find the first non-empty leaf - while ( ntree_->nodes_.empty() ) - { - - next_leaf_(); - if ( ntree_ == 0 ) - { - break; - } - } -} - -template < int D, class T, int max_capacity, int max_depth > -typename Ntree< D, T, max_capacity, max_depth >::iterator& -Ntree< D, T, max_capacity, max_depth >::iterator::operator++() -{ - node_++; - - while ( node_ >= ntree_->nodes_.size() ) - { - - next_leaf_(); - - node_ = 0; - if ( ntree_ == 0 ) - { - break; - } - } - - return *this; -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::iterator::next_leaf_() -{ - - // If we are on the last subntree, move up - while ( ntree_ and ( ntree_ != top_ ) and ntree_->my_subquad_ == N - 1 ) - { - ntree_ = ntree_->parent_; - } - - // Since we stop at the top, this should never happen! - assert( ntree_ != 0 ); - - // If we have reached the top, mark as invalid and return - if ( ntree_ == top_ ) - { - ntree_ = 0; - return; - } - - // Move to next sibling - ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; - - // Move down if this is not a leaf. - while ( not ntree_->is_leaf() ) - { - ntree_ = ntree_->children_[ 0 ]; - } -} - -// Proper mod which returns non-negative numbers -static inline double -mod( double x, double p ) -{ - x = std::fmod( x, p ); - if ( x < 0 ) - { - x += p; - } - return x; -} - -template < int D, class T, int max_capacity, int max_depth > -Ntree< D, T, max_capacity, max_depth >::masked_iterator::masked_iterator( Ntree< D, T, max_capacity, max_depth >& q, - const Mask< D >& mask, - const Position< D >& anchor ) - : ntree_( &q ) - , top_( &q ) - , allin_top_( 0 ) - , node_( 0 ) - , mask_( &mask ) - , anchor_( anchor ) - , anchors_() - , current_anchor_( 0 ) -{ - if ( ntree_->periodic_.any() ) - { - Box< D > mask_bb = mask_->get_bbox(); - - // Move lower left corner of mask into main image of layer - for ( int i = 0; i < D; ++i ) - { - if ( ntree_->periodic_[ i ] ) - { - anchor_[ i ] = - nest::mod( anchor_[ i ] + mask_bb.lower_left[ i ] - ntree_->lower_left_[ i ], ntree_->extent_[ i ] ) - - mask_bb.lower_left[ i ] + ntree_->lower_left_[ i ]; - } - } - anchors_.push_back( anchor_ ); - - // Add extra anchors for each dimension where this is needed - // (Assumes that the mask is not wider than the layer) - for ( int i = 0; i < D; ++i ) - { - if ( ntree_->periodic_[ i ] ) - { - int n = anchors_.size(); - if ( ( anchor_[ i ] + mask_bb.upper_right[ i ] - ntree_->lower_left_[ i ] ) > ntree_->extent_[ i ] ) - { - for ( int j = 0; j < n; ++j ) - { - Position< D > p = anchors_[ j ]; - p[ i ] -= ntree_->extent_[ i ]; - anchors_.push_back( p ); - } - } - } - } - } - - init_(); -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::masked_iterator::init_() -{ - node_ = 0; - allin_top_ = 0; - ntree_ = top_; - - if ( mask_->outside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) - { - - next_anchor_(); - } - else - { - - if ( mask_->inside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) - { - first_leaf_inside_(); - } - else - { - first_leaf_(); - } - - if ( ntree_->nodes_.empty() or ( not mask_->inside( ntree_->nodes_[ node_ ].first - anchor_ ) ) ) - { - ++( *this ); - } - } -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::masked_iterator::next_anchor_() -{ - ++current_anchor_; - if ( current_anchor_ >= anchors_.size() ) - { - // Done. Mark as invalid. - ntree_ = 0; - node_ = 0; - } - else - { - anchor_ = anchors_[ current_anchor_ ]; - init_(); - } -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::masked_iterator::next_leaf_() -{ - - // There are two states: the initial state, and "all in". In the - // all in state, we are in a subtree which is completely inside - // the mask. The allin_top_ is the top of this subtree. When - // exiting the subtree, the state changes to the initial - // state. In the initial state, we must check each quadrant to - // see if it is completely inside or outside the mask. If inside, - // we go all in. If outside, we move on to the next leaf. If - // neither, keep going until we find a leaf. Upon exiting from - // this function, we are either done (ntree_==0), or on a leaf - // node which at least intersects with the mask. If allin_top_!=0, - // the leaf is completely inside the mask. - - if ( allin_top_ ) - { - // state: all in - - // If we are on the last subtree, move up - while ( ntree_ and ( ntree_ != allin_top_ ) and ntree_->my_subquad_ == N - 1 ) - { - ntree_ = ntree_->parent_; - } - - // Since we stop at the top, this should never happen! - assert( ntree_ != 0 ); - - // If we reached the allin_top_, we are no longer all in. - if ( ntree_ != allin_top_ ) - { - - // Move to next sibling - ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; - - // Move down if this is not a leaf. - while ( not ntree_->is_leaf() ) - { - ntree_ = ntree_->children_[ 0 ]; - } - return; - } - - allin_top_ = 0; - // Will continue as not all in. - } - - // state: Not all in - - do - { - - // If we are on the last subtree, move up - while ( ntree_ and ( ntree_ != top_ ) and ntree_->my_subquad_ == N - 1 ) - { - ntree_ = ntree_->parent_; - } - - // Since we stop at the top, this should never happen! - assert( ntree_ != 0 ); - - // If we have reached the top, mark as invalid and return - if ( ntree_ == top_ ) - { - return next_anchor_(); - } - - // Move to next sibling - ntree_ = ntree_->parent_->children_[ ntree_->my_subquad_ + 1 ]; - // Create anchored position in two steps to avoid creating a new Position object. - anchored_position_ = ntree_->lower_left_; - anchored_position_ -= anchor_; - - if ( mask_->inside( Box< D >( anchored_position_, anchored_position_ + ntree_->extent_ ) ) ) - { - return first_leaf_inside_(); - } - - } while ( mask_->outside( Box< D >( anchored_position_, anchored_position_ + ntree_->extent_ ) ) ); - - return first_leaf_(); -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::masked_iterator::first_leaf_() -{ - while ( not ntree_->is_leaf() ) - { - - ntree_ = ntree_->children_[ 0 ]; - - if ( mask_->inside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) - { - return first_leaf_inside_(); - } - - if ( mask_->outside( Box< D >( ntree_->lower_left_ - anchor_, ntree_->lower_left_ - anchor_ + ntree_->extent_ ) ) ) - { - return next_leaf_(); - } - } -} - - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::masked_iterator::first_leaf_inside_() -{ - - allin_top_ = ntree_; - - while ( not ntree_->is_leaf() ) - { - ntree_ = ntree_->children_[ 0 ]; - } -} - -template < int D, class T, int max_capacity, int max_depth > -typename Ntree< D, T, max_capacity, max_depth >::masked_iterator& -Ntree< D, T, max_capacity, max_depth >::masked_iterator::operator++() -{ - ++node_; - - if ( allin_top_ == 0 ) - { - while ( - ( node_ < ntree_->nodes_.size() ) and ( not anchored_position_inside_mask( ntree_->nodes_[ node_ ].first ) ) ) - { - ++node_; - } - } - - while ( node_ >= ntree_->nodes_.size() ) - { - next_leaf_(); - - node_ = 0; - if ( ntree_ == 0 ) - { - break; - } - - if ( allin_top_ == 0 ) - { - while ( - ( node_ < ntree_->nodes_.size() ) and ( not anchored_position_inside_mask( ntree_->nodes_[ node_ ].first ) ) ) - { - ++node_; - } - } - } - - return *this; -} - -template < int D, class T, int max_capacity, int max_depth > -int -Ntree< D, T, max_capacity, max_depth >::subquad_( const Position< D >& pos ) -{ - int r = 0; - for ( int i = 0; i < D; ++i ) - { - // Comparing against an epsilon value in case there are round-off errors. - // Using a negative epsilon value because the round-off error may go both ways - // and the difference we check against may therefore be +/- 10^-16. - const bool in_left_half = - ( ( lower_left_[ i ] + extent_[ i ] / 2 ) - pos[ i ] ) > -std::numeric_limits< double >::epsilon(); - r += ( 1 << i ) * ( in_left_half ? 0 : 1 ); - } - - return r; -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::append_nodes_( std::vector< std::pair< Position< D >, T > >& v ) -{ - if ( leaf_ ) - { - std::copy( nodes_.begin(), nodes_.end(), std::back_inserter( v ) ); - } - else - { - for ( int i = 0; i < N; ++i ) - { - children_[ i ]->append_nodes_( v ); - } - } -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::append_nodes_( std::vector< std::pair< Position< D >, T > >& v, - const Mask< D >& mask, - const Position< D >& anchor ) -{ - if ( mask.outside( Box< D >( lower_left_ - anchor, lower_left_ - anchor + extent_ ) ) ) - { - return; - } - if ( mask.inside( Box< D >( lower_left_ - anchor, lower_left_ - anchor + extent_ ) ) ) - { - return append_nodes_( v ); - } - if ( leaf_ ) - { - - for ( typename std::vector< std::pair< Position< D >, T > >::iterator i = nodes_.begin(); i != nodes_.end(); ++i ) - { - if ( mask.inside( i->first - anchor ) ) - { - v.push_back( *i ); - } - } - } - else - { - for ( int i = 0; i < N; ++i ) - { - children_[ i ]->append_nodes_( v, mask, anchor ); - } - } -} - -template < int D, class T, int max_capacity, int max_depth > -typename Ntree< D, T, max_capacity, max_depth >::iterator -Ntree< D, T, max_capacity, max_depth >::insert( Position< D > pos, const T& node ) -{ - if ( periodic_.any() ) - { - // Map position into standard range when using periodic b.c. Only necessary when - // inserting positions during source driven connect when target has periodic b.c. - // May be inefficient. - for ( int i = 0; i < D; ++i ) - { - if ( periodic_[ i ] ) - { - pos[ i ] = lower_left_[ i ] + std::fmod( pos[ i ] - lower_left_[ i ], extent_[ i ] ); - if ( pos[ i ] < lower_left_[ i ] ) - { - pos[ i ] += extent_[ i ]; - } - } - } - } - - if ( leaf_ and ( nodes_.size() >= max_capacity ) and my_depth_ < max_depth ) - { - split_(); - } - if ( leaf_ ) - { - - for ( int i = 0; i < D; ++i ) - { - // Comparing against an epsilon value in case there are round-off errors. - // Using a negative epsilon value because the round-off error may go both ways - // and the difference we check against may therefore be +/- 10^-16. - assert( ( pos - lower_left_ )[ i ] > -std::numeric_limits< double >::epsilon() - and ( lower_left_ + extent_ - pos )[ i ] > -std::numeric_limits< double >::epsilon() ); - } - - nodes_.push_back( std::pair< Position< D >, T >( pos, node ) ); - - return iterator( *this, nodes_.size() - 1 ); - } - else - { - - return children_[ subquad_( pos ) ]->insert( pos, node ); - } -} - -template < int D, class T, int max_capacity, int max_depth > -void -Ntree< D, T, max_capacity, max_depth >::split_() -{ - assert( leaf_ ); - - for ( int j = 0; j < N; ++j ) - { - Position< D > lower_left = lower_left_; - for ( int i = 0; i < D; ++i ) - { - if ( j & ( 1 << i ) ) - { - lower_left[ i ] += extent_[ i ] * 0.5; - } - } - - children_[ j ] = new Ntree< D, T, max_capacity, max_depth >( lower_left, extent_ * 0.5, 0, this, j ); - } - - for ( typename std::vector< std::pair< Position< D >, T > >::iterator i = nodes_.begin(); i != nodes_.end(); ++i ) - { - children_[ subquad_( i->first ) ]->insert( i->first, i->second ); - } - - nodes_.clear(); - - leaf_ = false; -} -} - -#endif diff --git a/nestkernel/parameter.cpp b/nestkernel/parameter.cpp index f5d5301f35..3346b4101c 100644 --- a/nestkernel/parameter.cpp +++ b/nestkernel/parameter.cpp @@ -22,12 +22,11 @@ #include +#include "nest.h" #include "node.h" #include "node_collection.h" -#include "spatial.h" -#include "vp_manager_impl.h" - #include "parameter.h" +#include "spatial.h" namespace nest diff --git a/nestkernel/per_thread_bool_indicator.cpp b/nestkernel/per_thread_bool_indicator.cpp index 4032a7320f..29622d9db6 100644 --- a/nestkernel/per_thread_bool_indicator.cpp +++ b/nestkernel/per_thread_bool_indicator.cpp @@ -24,7 +24,8 @@ // Includes from nestkernel #include "kernel_manager.h" -#include "stopwatch_impl.h" + +#include "simulation_manager.h" namespace nest { @@ -65,7 +66,7 @@ PerThreadBoolIndicator::initialize( const size_t num_threads, const bool status bool PerThreadBoolIndicator::all_false() const { - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); // We need two barriers here to ensure that no thread can continue and change the result // before all threads have determined the result. #pragma omp barrier @@ -74,42 +75,42 @@ PerThreadBoolIndicator::all_false() const bool ret = ( are_true_ == 0 ); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); return ret; } bool PerThreadBoolIndicator::all_true() const { - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier bool ret = ( are_true_ == size_ ); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); return ret; } bool PerThreadBoolIndicator::any_false() const { - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier bool ret = ( are_true_ < size_ ); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); return ret; } bool PerThreadBoolIndicator::any_true() const { - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier bool ret = ( are_true_ > 0 ); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); return ret; } diff --git a/nestkernel/proxynode.cpp b/nestkernel/proxynode.cpp index af4b624a57..43488457a2 100644 --- a/nestkernel/proxynode.cpp +++ b/nestkernel/proxynode.cpp @@ -25,6 +25,7 @@ // Includes from nestkernel: #include "connection.h" #include "kernel_manager.h" +#include "model_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/random_manager.cpp b/nestkernel/random_manager.cpp index db0a58fd65..a7f3173f4c 100644 --- a/nestkernel/random_manager.cpp +++ b/nestkernel/random_manager.cpp @@ -27,9 +27,12 @@ #include // Includes from nestkernel: +#include "dictutils.h" #include "kernel_manager.h" +#include "mpi_manager.h" +#include "nest_names.h" #include "random_generators.h" -#include "vp_manager_impl.h" +#include "vp_manager.h" // Includes from libnestutil: #ifdef HAVE_RANDOM123 diff --git a/nestkernel/recording_backend_ascii.cpp b/nestkernel/recording_backend_ascii.cpp index 773aa36a82..b7f6d8ff54 100644 --- a/nestkernel/recording_backend_ascii.cpp +++ b/nestkernel/recording_backend_ascii.cpp @@ -24,13 +24,17 @@ #include "compose.hpp" // Includes from nestkernel: +#include "io_manager.h" +#include "logging.h" +#include "logging_manager.h" +#include "node_manager.h" +#include "recording_backend_ascii.h" #include "recording_device.h" -#include "vp_manager_impl.h" +#include "simulation_manager.h" // includes from sli: #include "dictutils.h" -#include "recording_backend_ascii.h" const unsigned int nest::RecordingBackendASCII::ASCII_REC_BACKEND_VERSION = 2; diff --git a/nestkernel/recording_backend_memory.cpp b/nestkernel/recording_backend_memory.cpp index 3ff816c685..6c484f6e66 100644 --- a/nestkernel/recording_backend_memory.cpp +++ b/nestkernel/recording_backend_memory.cpp @@ -21,10 +21,9 @@ */ // Includes from nestkernel: -#include "recording_device.h" -#include "vp_manager_impl.h" - #include "recording_backend_memory.h" +#include "recording_device.h" +#include "simulation_manager.h" nest::RecordingBackendMemory::RecordingBackendMemory() { diff --git a/nestkernel/recording_backend_mpi.cpp b/nestkernel/recording_backend_mpi.cpp index 3c048211a0..127adb1647 100644 --- a/nestkernel/recording_backend_mpi.cpp +++ b/nestkernel/recording_backend_mpi.cpp @@ -26,6 +26,9 @@ // Includes from nestkernel: #include "exceptions.h" +#include "io_manager.h" +#include "logging.h" +#include "logging_manager.h" #include "recording_backend_mpi.h" #include "recording_device.h" diff --git a/nestkernel/recording_backend_sionlib.cpp b/nestkernel/recording_backend_sionlib.cpp index 5aabb26ebc..33753117e5 100644 --- a/nestkernel/recording_backend_sionlib.cpp +++ b/nestkernel/recording_backend_sionlib.cpp @@ -36,10 +36,8 @@ #include "../nest/neststartup.h" // Includes from nestkernel: -#include "recording_device.h" -#include "vp_manager_impl.h" - #include "recording_backend_sionlib.h" +#include "recording_device.h" const unsigned int nest::RecordingBackendSIONlib::SIONLIB_REC_BACKEND_VERSION = 2; const unsigned int nest::RecordingBackendSIONlib::DEV_NAME_BUFFERSIZE = 32; diff --git a/nestkernel/recording_device.cpp b/nestkernel/recording_device.cpp index 205fde2e6b..c827d4da90 100644 --- a/nestkernel/recording_device.cpp +++ b/nestkernel/recording_device.cpp @@ -21,10 +21,11 @@ */ // Includes from libnestutil: +#include "recording_device.h" #include "compose.hpp" +#include "io_manager.h" #include "kernel_manager.h" - -#include "recording_device.h" +#include "simulation_manager.h" nest::RecordingDevice::RecordingDevice() : DeviceNode() diff --git a/nestkernel/ring_buffer.cpp b/nestkernel/ring_buffer.cpp index 48ee802b1c..1c0275ed2e 100644 --- a/nestkernel/ring_buffer.cpp +++ b/nestkernel/ring_buffer.cpp @@ -21,6 +21,7 @@ */ #include "ring_buffer.h" +#include "connection_manager.h" nest::RingBuffer::RingBuffer() : buffer_( kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(), 0.0 ) diff --git a/nestkernel/ring_buffer.h b/nestkernel/ring_buffer.h index 9e7328f766..e4bbf70ddf 100644 --- a/nestkernel/ring_buffer.h +++ b/nestkernel/ring_buffer.h @@ -29,6 +29,7 @@ #include // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" #include "nest_time.h" #include "nest_types.h" @@ -422,6 +423,36 @@ MultiChannelInputBuffer< num_channels >::size() const return buffer_.size(); } +template < unsigned int num_channels > +MultiChannelInputBuffer< num_channels >::MultiChannelInputBuffer() + : buffer_( kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(), + std::array< double, num_channels >() ) +{ +} + +template < unsigned int num_channels > +void +MultiChannelInputBuffer< num_channels >::resize() +{ + const size_t size = kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(); + if ( buffer_.size() != size ) + { + buffer_.resize( size, std::array< double, num_channels >() ); + } +} + +template < unsigned int num_channels > +void +MultiChannelInputBuffer< num_channels >::clear() +{ + resize(); // does nothing if size is fine + // set all elements to 0.0 + for ( size_t slot = 0; slot < buffer_.size(); ++slot ) + { + reset_values_all_channels( slot ); + } +} + } // namespace nest diff --git a/nestkernel/ring_buffer_impl.h b/nestkernel/ring_buffer_impl.h deleted file mode 100644 index 76db8a6fb6..0000000000 --- a/nestkernel/ring_buffer_impl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ring_buffer_impl.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 RING_BUFFER_IMPL_H -#define RING_BUFFER_IMPL_H - -#include "ring_buffer.h" - -template < unsigned int num_channels > -nest::MultiChannelInputBuffer< num_channels >::MultiChannelInputBuffer() - : buffer_( kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(), - std::array< double, num_channels >() ) -{ -} - -template < unsigned int num_channels > -void -nest::MultiChannelInputBuffer< num_channels >::resize() -{ - const size_t size = kernel().connection_manager.get_min_delay() + kernel().connection_manager.get_max_delay(); - if ( buffer_.size() != size ) - { - buffer_.resize( size, std::array< double, num_channels >() ); - } -} - -template < unsigned int num_channels > -void -nest::MultiChannelInputBuffer< num_channels >::clear() -{ - resize(); // does nothing if size is fine - // set all elements to 0.0 - for ( size_t slot = 0; slot < buffer_.size(); ++slot ) - { - reset_values_all_channels( slot ); - } -} - -#endif diff --git a/nestkernel/secondary_event.h b/nestkernel/secondary_event.h index 00676e68f1..746e8bc0e4 100644 --- a/nestkernel/secondary_event.h +++ b/nestkernel/secondary_event.h @@ -472,6 +472,31 @@ SICEvent::clone() const return new SICEvent( *this ); } +template < typename DataType, typename Subclass > +void +DataSecondaryEvent< DataType, Subclass >::add_syn_id( const synindex synid ) +{ + kernel().vp_manager.assert_thread_parallel(); + + // This is done during connection model cloning, which happens thread-parallel. + // To not risk trashing the set data structure, we let only master register the + // new synid. This is not performance critical and avoiding collisions elsewhere + // would be more difficult, so we do it here in a master section. +#pragma omp master + { + supported_syn_ids_.insert( synid ); + } +#pragma omp barrier +} + +template < typename DataType, typename Subclass > +void +DataSecondaryEvent< DataType, Subclass >::set_coeff_length( const size_t coeff_length ) +{ + kernel().vp_manager.assert_single_threaded(); + coeff_length_ = coeff_length; +} + } // namespace nest #endif /* #ifndef SECONDARY_EVENT_H */ diff --git a/nestkernel/secondary_event_impl.h b/nestkernel/secondary_event_impl.h deleted file mode 100644 index 1ad6fe92ee..0000000000 --- a/nestkernel/secondary_event_impl.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * secondary_event_impl.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 . - * - */ - -#include "secondary_event.h" - -// Includes from nestkernel -#include "kernel_manager.h" - -template < typename DataType, typename Subclass > -void -nest::DataSecondaryEvent< DataType, Subclass >::add_syn_id( const nest::synindex synid ) -{ - kernel().vp_manager.assert_thread_parallel(); - - // This is done during connection model cloning, which happens thread-parallel. - // To not risk trashing the set data structure, we let only master register the - // new synid. This is not performance critical and avoiding collisions elsewhere - // would be more difficult, so we do it here in a master section. -#pragma omp master - { - supported_syn_ids_.insert( synid ); - } -#pragma omp barrier -} - -template < typename DataType, typename Subclass > -void -nest::DataSecondaryEvent< DataType, Subclass >::set_coeff_length( const size_t coeff_length ) -{ - kernel().vp_manager.assert_single_threaded(); - coeff_length_ = coeff_length; -} diff --git a/nestkernel/simulation_manager.cpp b/nestkernel/simulation_manager.cpp index 9f23d7f89b..3ec93ffc11 100644 --- a/nestkernel/simulation_manager.cpp +++ b/nestkernel/simulation_manager.cpp @@ -34,10 +34,16 @@ #include "numerics.h" // Includes from nestkernel: -#include "connection_manager_impl.h" #include "event_delivery_manager.h" +#include "io_manager.h" #include "kernel_manager.h" -#include "stopwatch_impl.h" +#include "logging_manager.h" +#include "model_manager.h" +#include "music_manager.h" +#include "node_manager.h" +#include "random_manager.h" +#include "sp_manager.h" +#include // Includes from sli: #include "dictutils.h" @@ -72,6 +78,10 @@ nest::SimulationManager::SimulationManager() void nest::SimulationManager::initialize( const bool adjust_number_of_threads_or_rng_only ) { + sw_omp_synchronization_construction_.reset(); + sw_omp_synchronization_simulation_.reset(); + sw_mpi_synchronization_.reset(); + if ( adjust_number_of_threads_or_rng_only ) { return; @@ -483,6 +493,12 @@ nest::SimulationManager::get_status( DictionaryDatum& d ) sw_deliver_spike_data_.get_status( d, names::time_deliver_spike_data, names::time_deliver_spike_data_cpu ); sw_deliver_secondary_data_.get_status( d, names::time_deliver_secondary_data, names::time_deliver_secondary_data_cpu ); + sw_omp_synchronization_construction_.get_status( + d, names::time_omp_synchronization_construction, names::time_omp_synchronization_construction_cpu ); + sw_omp_synchronization_simulation_.get_status( + d, names::time_omp_synchronization_simulation, names::time_omp_synchronization_simulation_cpu ); + sw_mpi_synchronization_.get_status( d, names::time_mpi_synchronization, names::time_mpi_synchronization_cpu ); + def< double >( d, names::eprop_update_interval, eprop_update_interval_ ); def< double >( d, names::eprop_learning_window, eprop_learning_window_ ); def< bool >( d, names::eprop_reset_neurons_on_update, eprop_reset_neurons_on_update_ ); @@ -507,6 +523,9 @@ nest::SimulationManager::prepare() "earlier error. Please run ResetKernel first." ); } + sw_omp_synchronization_simulation_.reset(); + sw_mpi_synchronization_.reset(); + // reset profiling timers reset_timers_for_dynamics(); kernel().event_delivery_manager.reset_timers_for_dynamics(); @@ -734,9 +753,9 @@ nest::SimulationManager::call_update_() void nest::SimulationManager::update_connection_infrastructure( const size_t tid ) { - kernel().get_omp_synchronization_construction_stopwatch().start(); + get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + get_omp_synchronization_construction_stopwatch().stop(); sw_communicate_prepare_.start(); @@ -746,9 +765,9 @@ nest::SimulationManager::update_connection_infrastructure( const size_t tid ) kernel().connection_manager.collect_compressed_spike_data( tid ); sw_gather_target_data_.stop(); - kernel().get_omp_synchronization_construction_stopwatch().start(); + get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier // wait for all threads to finish sorting - kernel().get_omp_synchronization_construction_stopwatch().stop(); + get_omp_synchronization_construction_stopwatch().stop(); #pragma omp single { @@ -763,15 +782,15 @@ nest::SimulationManager::update_connection_infrastructure( const size_t tid ) if ( kernel().connection_manager.secondary_connections_exist() ) { - kernel().get_omp_synchronization_construction_stopwatch().start(); + get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + get_omp_synchronization_construction_stopwatch().stop(); kernel().connection_manager.compute_compressed_secondary_recv_buffer_positions( tid ); - kernel().get_omp_synchronization_construction_stopwatch().start(); + get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + get_omp_synchronization_construction_stopwatch().stop(); #pragma omp single { @@ -805,9 +824,9 @@ nest::SimulationManager::update_connection_infrastructure( const size_t tid ) kernel().connection_manager.compress_secondary_send_buffer_pos( tid ); } - kernel().get_omp_synchronization_construction_stopwatch().start(); + get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + get_omp_synchronization_construction_stopwatch().stop(); #pragma omp single { kernel().connection_manager.clear_compressed_spike_data_map(); @@ -885,9 +904,9 @@ nest::SimulationManager::update_() // MUSIC *before* MUSIC time is advanced // wait until all threads are done -> synchronize - kernel().get_omp_synchronization_simulation_stopwatch().start(); + get_omp_synchronization_simulation_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_simulation_stopwatch().stop(); + get_omp_synchronization_simulation_stopwatch().stop(); // the following block is executed by the master thread only // the other threads are enforced to wait at the end of the block #pragma omp master @@ -950,9 +969,9 @@ nest::SimulationManager::update_() done.push_back( done_p ); } // parallel section ends, wait until all threads are done -> synchronize - kernel().get_omp_synchronization_simulation_stopwatch().start(); + get_omp_synchronization_simulation_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_simulation_stopwatch().stop(); + get_omp_synchronization_simulation_stopwatch().stop(); // the following block is executed by a single thread // the other threads wait at the end of the block @@ -1012,9 +1031,9 @@ nest::SimulationManager::update_() Node* node = i->get_node(); node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms() ); } - kernel().get_omp_synchronization_simulation_stopwatch().start(); + get_omp_synchronization_simulation_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_simulation_stopwatch().stop(); + get_omp_synchronization_simulation_stopwatch().stop(); #pragma omp single { kernel().sp_manager.update_structural_plasticity(); @@ -1051,9 +1070,9 @@ nest::SimulationManager::update_() sw_update_.stop(); // parallel section ends, wait until all threads are done -> synchronize - kernel().get_omp_synchronization_simulation_stopwatch().start(); + get_omp_synchronization_simulation_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_simulation_stopwatch().stop(); + get_omp_synchronization_simulation_stopwatch().stop(); // the following block is executed by the master thread only // the other threads are enforced to wait at the end of the block @@ -1099,9 +1118,9 @@ nest::SimulationManager::update_() #ifdef HAVE_SIONLIB kernel().io_manager.post_step_hook(); // enforce synchronization after post-step activities of the recording backends - kernel().get_omp_synchronization_simulation_stopwatch().start(); + get_omp_synchronization_simulation_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_simulation_stopwatch().stop(); + get_omp_synchronization_simulation_stopwatch().stop(); #endif const double end_current_update = sw_simulate_.elapsed(); diff --git a/nestkernel/simulation_manager.h b/nestkernel/simulation_manager.h index 1c83bea508..c7eed7cc23 100644 --- a/nestkernel/simulation_manager.h +++ b/nestkernel/simulation_manager.h @@ -189,6 +189,26 @@ class SimulationManager : public ManagerInterface Time get_eprop_learning_window() const; bool get_eprop_reset_neurons_on_update() const; + //! Get the stopwatch to measure the time each thread is idle during network construction. + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded >& + get_omp_synchronization_construction_stopwatch() + { + return sw_omp_synchronization_construction_; + } + + //! Get the stopwatch to measure the time each thread is idle during simulation. + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded >& + get_omp_synchronization_simulation_stopwatch() + { + return sw_omp_synchronization_simulation_; + } + + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::MasterOnly >& + get_mpi_synchronization_stopwatch() + { + return sw_mpi_synchronization_; + } + private: void call_update_(); //!< actually run simulation, aka wrap update_ void update_(); //! actually perform simulation @@ -238,6 +258,10 @@ class SimulationManager : public ManagerInterface Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_deliver_spike_data_; Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_deliver_secondary_data_; + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_omp_synchronization_construction_; + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::Threaded > sw_omp_synchronization_simulation_; + Stopwatch< StopwatchGranularity::Detailed, StopwatchParallelism::MasterOnly > sw_mpi_synchronization_; + double eprop_update_interval_; double eprop_learning_window_; bool eprop_reset_neurons_on_update_; diff --git a/nestkernel/slice_ring_buffer.cpp b/nestkernel/slice_ring_buffer.cpp index ab12ca3aa4..6a6c4563ac 100644 --- a/nestkernel/slice_ring_buffer.cpp +++ b/nestkernel/slice_ring_buffer.cpp @@ -26,6 +26,9 @@ #include #include +#include "connection_manager.h" +#include "event_delivery_manager.h" + nest::SliceRingBuffer::SliceRingBuffer() : refract_( std::numeric_limits< long >::max(), 0, 0 ) { diff --git a/nestkernel/slice_ring_buffer.h b/nestkernel/slice_ring_buffer.h index 62999fbc90..e14bfe9926 100644 --- a/nestkernel/slice_ring_buffer.h +++ b/nestkernel/slice_ring_buffer.h @@ -33,8 +33,8 @@ #include "config.h" // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" -#include "nest_types.h" namespace nest { diff --git a/nestkernel/sonata_connector.cpp b/nestkernel/sonata_connector.cpp index b44ae89640..59b7583c66 100644 --- a/nestkernel/sonata_connector.cpp +++ b/nestkernel/sonata_connector.cpp @@ -30,7 +30,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -#include "vp_manager_impl.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/source_table.cpp b/nestkernel/source_table.cpp index d9fcd7af1c..f82fca8312 100644 --- a/nestkernel/source_table.cpp +++ b/nestkernel/source_table.cpp @@ -25,12 +25,9 @@ // Includes from nestkernel: #include "connection_manager.h" -#include "connection_manager_impl.h" #include "kernel_manager.h" -#include "mpi_manager_impl.h" +#include "model_manager.h" #include "source_table.h" -#include "stopwatch_impl.h" -#include "vp_manager_impl.h" nest::SourceTable::SourceTable() { @@ -230,9 +227,9 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t } } } - kernel().get_omp_synchronization_construction_stopwatch().start(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().start(); #pragma omp barrier - kernel().get_omp_synchronization_construction_stopwatch().stop(); + kernel().simulation_manager.get_omp_synchronization_construction_stopwatch().stop(); #pragma omp single { @@ -245,7 +242,7 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t cit != ( *unique_secondary_source_node_id_syn_id ).end(); ++cit ) { - const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( cit->first ); + const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( cit->first ); const size_t event_size = kernel().model_manager.get_secondary_event_prototype( cit->second, tid ).size(); buffer_pos_of_source_node_id_syn_id.insert( @@ -280,7 +277,7 @@ nest::SourceTable::source_should_be_processed_( const size_t rank_start, const size_t rank_end, const Source& source ) const { - const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( source.get_node_id() ); + const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( source.get_node_id() ); return not( source.is_processed() or source.is_disabled() @@ -412,7 +409,7 @@ nest::SourceTable::get_next_target_data( const size_t tid, // communicated via MPI, so we prepare to return the relevant data // set the source rank - source_rank = kernel().mpi_manager.get_process_id_of_node_id( current_source.get_node_id() ); + source_rank = kernel().vp_manager.get_process_id_of_node_id( current_source.get_node_id() ); if ( not populate_target_data_fields_( current_position, current_source, source_rank, next_target_data ) ) { diff --git a/nestkernel/sp_manager.cpp b/nestkernel/sp_manager.cpp index 4705b7de64..294fb6ec0c 100644 --- a/nestkernel/sp_manager.cpp +++ b/nestkernel/sp_manager.cpp @@ -28,11 +28,15 @@ // Includes from nestkernel: #include "conn_builder.h" #include "conn_parameter.h" +#include "connection_manager.h" #include "connector_base.h" #include "connector_model.h" #include "kernel_manager.h" +#include "logging.h" +#include "logging_manager.h" +#include "model_manager.h" +#include "nest.h" #include "nest_names.h" -#include "sp_manager_impl.h" namespace nest { diff --git a/nestkernel/sp_manager.h b/nestkernel/sp_manager.h index 79cc92a72a..90b3828de3 100644 --- a/nestkernel/sp_manager.h +++ b/nestkernel/sp_manager.h @@ -229,6 +229,18 @@ SPManager::get_structural_plasticity_update_interval() const return structural_plasticity_update_interval_; } +template < typename GrowthCurve > +void +SPManager::register_growth_curve( const std::string& name ) +{ + assert( not growthcurvedict_->known( name ) ); + GenericGrowthCurveFactory* nc = new GrowthCurveFactory< GrowthCurve >(); + assert( nc ); + const int id = growthcurve_factories_.size(); + growthcurve_factories_.push_back( nc ); + growthcurvedict_->insert( name, id ); +} + } // namespace nest #endif /* #ifndef SP_MANAGER_H */ diff --git a/nestkernel/sp_manager_impl.h b/nestkernel/sp_manager_impl.h deleted file mode 100644 index 791ac78db2..0000000000 --- a/nestkernel/sp_manager_impl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * sp_manager_impl.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 SP_MANAGER_IMPL_H -#define SP_MANAGER_IMPL_H - -#include "sp_manager.h" - -// C++ includes: -#include - -// Includes from nestkernel: -#include "growth_curve.h" -#include "growth_curve_factory.h" - -namespace nest -{ - -template < typename GrowthCurve > -void -SPManager::register_growth_curve( const std::string& name ) -{ - assert( not growthcurvedict_->known( name ) ); - GenericGrowthCurveFactory* nc = new GrowthCurveFactory< GrowthCurve >(); - assert( nc ); - const int id = growthcurve_factories_.size(); - growthcurve_factories_.push_back( nc ); - growthcurvedict_->insert( name, id ); -} - -} // namespace nest - -#endif /* SP_MANAGER_IMPL_H */ diff --git a/nestkernel/sparse_node_array.cpp b/nestkernel/sparse_node_array.cpp index 6154eace5d..b2385a8471 100644 --- a/nestkernel/sparse_node_array.cpp +++ b/nestkernel/sparse_node_array.cpp @@ -26,7 +26,6 @@ #include "exceptions.h" #include "kernel_manager.h" #include "node.h" -#include "vp_manager_impl.h" nest::SparseNodeArray::NodeEntry::NodeEntry( Node& node, size_t node_id ) diff --git a/nestkernel/spatial.cpp b/nestkernel/spatial.cpp index 603cd814d3..f776ba2216 100644 --- a/nestkernel/spatial.cpp +++ b/nestkernel/spatial.cpp @@ -41,7 +41,6 @@ // Includes from spatial: #include "grid_layer.h" -#include "layer_impl.h" namespace nest diff --git a/nestkernel/stimulation_backend_mpi.cpp b/nestkernel/stimulation_backend_mpi.cpp index 8f908d24ce..14c1ace62f 100644 --- a/nestkernel/stimulation_backend_mpi.cpp +++ b/nestkernel/stimulation_backend_mpi.cpp @@ -26,7 +26,11 @@ #include // Includes from nestkernel: +#include "connection_manager.h" +#include "io_manager.h" #include "kernel_manager.h" +#include "logging.h" +#include "logging_manager.h" #include "stimulation_backend.h" #include "stimulation_backend_mpi.h" #include "stimulation_device.h" diff --git a/nestkernel/stimulation_device.cpp b/nestkernel/stimulation_device.cpp index ab3c800c9b..77a7eb70b8 100644 --- a/nestkernel/stimulation_device.cpp +++ b/nestkernel/stimulation_device.cpp @@ -23,6 +23,7 @@ // Includes from nestkernel: #include "stimulation_device.h" +#include "io_manager.h" #include "kernel_manager.h" diff --git a/nestkernel/stopwatch.h b/nestkernel/stopwatch.h index 57b2c3ee10..637bb8ad80 100644 --- a/nestkernel/stopwatch.h +++ b/nestkernel/stopwatch.h @@ -23,21 +23,18 @@ #ifndef STOPWATCH_H #define STOPWATCH_H -// C includes: -#include - // C++ includes: #include "arraydatum.h" #include "dictdatum.h" #include "dictutils.h" #include -#include -#include #include #include // Includes from nestkernel: #include "exceptions.h" +#include "kernel_manager.h" +#include "vp_manager.h" namespace nest { @@ -524,5 +521,89 @@ class Stopwatch< detailed_timer, std::vector< timers::StopwatchTimer< CLOCK_THREAD_CPUTIME_ID > > cputime_timers_; }; +template < StopwatchGranularity detailed_timer > +void +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::start() +{ + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].start(); + cputime_timers_[ kernel().vp_manager.get_thread_id() ].start(); +} + +template < StopwatchGranularity detailed_timer > +void +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::stop() +{ + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); + cputime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); +} + +template < StopwatchGranularity detailed_timer > +bool +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::is_running_() const +{ + kernel().vp_manager.assert_thread_parallel(); + + return walltime_timers_[ kernel().vp_manager.get_thread_id() ].is_running_(); +} + +template < StopwatchGranularity detailed_timer > +double +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::elapsed( timers::timeunit_t + timeunit ) const +{ + kernel().vp_manager.assert_thread_parallel(); + + return walltime_timers_[ kernel().vp_manager.get_thread_id() ].elapsed( timeunit ); +} + +template < StopwatchGranularity detailed_timer > +void +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::print( const std::string& msg, + timers::timeunit_t timeunit, + std::ostream& os ) const +{ + kernel().vp_manager.assert_thread_parallel(); + + walltime_timers_[ kernel().vp_manager.get_thread_id() ].print( msg, timeunit, os ); +} + +template < StopwatchGranularity detailed_timer > +void +Stopwatch< detailed_timer, + StopwatchParallelism::Threaded, + std::enable_if_t< use_threaded_timers + and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::reset() +{ + kernel().vp_manager.assert_single_threaded(); + + const size_t num_threads = kernel().vp_manager.get_num_threads(); + walltime_timers_.resize( num_threads ); + cputime_timers_.resize( num_threads ); + for ( size_t i = 0; i < num_threads; ++i ) + { + walltime_timers_[ i ].reset(); + cputime_timers_[ i ].reset(); + } +} + } /* namespace nest */ #endif /* STOPWATCH_H */ diff --git a/nestkernel/stopwatch_impl.h b/nestkernel/stopwatch_impl.h deleted file mode 100644 index 123804117e..0000000000 --- a/nestkernel/stopwatch_impl.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * stopwatch_impl.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 . - * - */ - -#include "kernel_manager.h" -#include "stopwatch.h" - -namespace nest -{ - -template < StopwatchGranularity detailed_timer > -void -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::start() -{ - kernel().vp_manager.assert_thread_parallel(); - - walltime_timers_[ kernel().vp_manager.get_thread_id() ].start(); - cputime_timers_[ kernel().vp_manager.get_thread_id() ].start(); -} - -template < StopwatchGranularity detailed_timer > -void -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::stop() -{ - kernel().vp_manager.assert_thread_parallel(); - - walltime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); - cputime_timers_[ kernel().vp_manager.get_thread_id() ].stop(); -} - -template < StopwatchGranularity detailed_timer > -bool -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::is_running_() const -{ - kernel().vp_manager.assert_thread_parallel(); - - return walltime_timers_[ kernel().vp_manager.get_thread_id() ].is_running_(); -} - -template < StopwatchGranularity detailed_timer > -double -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::elapsed( timers::timeunit_t - timeunit ) const -{ - kernel().vp_manager.assert_thread_parallel(); - - return walltime_timers_[ kernel().vp_manager.get_thread_id() ].elapsed( timeunit ); -} - -template < StopwatchGranularity detailed_timer > -void -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::print( const std::string& msg, - timers::timeunit_t timeunit, - std::ostream& os ) const -{ - kernel().vp_manager.assert_thread_parallel(); - - walltime_timers_[ kernel().vp_manager.get_thread_id() ].print( msg, timeunit, os ); -} - -template < StopwatchGranularity detailed_timer > -void -Stopwatch< detailed_timer, - StopwatchParallelism::Threaded, - std::enable_if_t< use_threaded_timers - and ( detailed_timer == StopwatchGranularity::Normal or use_detailed_timers ) > >::reset() -{ - kernel().vp_manager.assert_single_threaded(); - - const size_t num_threads = kernel().vp_manager.get_num_threads(); - walltime_timers_.resize( num_threads ); - cputime_timers_.resize( num_threads ); - for ( size_t i = 0; i < num_threads; ++i ) - { - walltime_timers_[ i ].reset(); - cputime_timers_[ i ].reset(); - } -} -} diff --git a/nestkernel/synaptic_element.cpp b/nestkernel/synaptic_element.cpp index cd51c16861..a06e866f4f 100644 --- a/nestkernel/synaptic_element.cpp +++ b/nestkernel/synaptic_element.cpp @@ -25,6 +25,8 @@ // Includes from nestkernel: #include "exceptions.h" #include "kernel_manager.h" +#include "nest_names.h" +#include "sp_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/target_identifier.h b/nestkernel/target_identifier.h index 82e5356260..94f9bbb88c 100644 --- a/nestkernel/target_identifier.h +++ b/nestkernel/target_identifier.h @@ -30,6 +30,8 @@ #include "compose.hpp" #include "kernel_manager.h" +#include "node.h" +#include "node_manager.h" namespace nest { diff --git a/nestkernel/target_table.cpp b/nestkernel/target_table.cpp index d9d06a8c4e..10af1c991e 100644 --- a/nestkernel/target_table.cpp +++ b/nestkernel/target_table.cpp @@ -23,6 +23,9 @@ // Includes from nestkernel: #include "target_table.h" #include "kernel_manager.h" +#include "model_manager.h" +#include "mpi_manager.h" +#include "vp_manager.h" // Includes from libnestutil #include "vector_util.h" diff --git a/nestkernel/target_table_devices.cpp b/nestkernel/target_table_devices.cpp index da106e9b43..c162239f00 100644 --- a/nestkernel/target_table_devices.cpp +++ b/nestkernel/target_table_devices.cpp @@ -21,21 +21,25 @@ */ // Includes from nestkernel: +#include "target_table_devices.h" #include "connector_base.h" +#include "connector_model.h" #include "kernel_manager.h" -#include "target_table_devices_impl.h" -#include "vp_manager_impl.h" +#include "model_manager.h" -nest::TargetTableDevices::TargetTableDevices() +namespace nest +{ + +TargetTableDevices::TargetTableDevices() { } -nest::TargetTableDevices::~TargetTableDevices() +TargetTableDevices::~TargetTableDevices() { } void -nest::TargetTableDevices::initialize() +TargetTableDevices::initialize() { const size_t num_threads = kernel().vp_manager.get_num_threads(); target_to_devices_.resize( num_threads ); @@ -44,7 +48,7 @@ nest::TargetTableDevices::initialize() } void -nest::TargetTableDevices::finalize() +TargetTableDevices::finalize() { for ( size_t tid = 0; tid < target_to_devices_.size(); ++tid ) { @@ -74,7 +78,7 @@ nest::TargetTableDevices::finalize() } void -nest::TargetTableDevices::resize_to_number_of_neurons() +TargetTableDevices::resize_to_number_of_neurons() { #pragma omp parallel { @@ -86,7 +90,7 @@ nest::TargetTableDevices::resize_to_number_of_neurons() } void -nest::TargetTableDevices::resize_to_number_of_synapse_types() +TargetTableDevices::resize_to_number_of_synapse_types() { kernel().vp_manager.assert_thread_parallel(); @@ -104,7 +108,7 @@ nest::TargetTableDevices::resize_to_number_of_synapse_types() } void -nest::TargetTableDevices::get_connections_to_devices_( const size_t requested_source_node_id, +TargetTableDevices::get_connections_to_devices_( const size_t requested_source_node_id, const size_t requested_target_node_id, const size_t tid, const synindex syn_id, @@ -130,7 +134,7 @@ nest::TargetTableDevices::get_connections_to_devices_( const size_t requested_so } void -nest::TargetTableDevices::get_connections_to_device_for_lid_( const size_t lid, +TargetTableDevices::get_connections_to_device_for_lid_( const size_t lid, const size_t requested_target_node_id, const size_t tid, const synindex syn_id, @@ -150,7 +154,7 @@ nest::TargetTableDevices::get_connections_to_device_for_lid_( const size_t lid, } void -nest::TargetTableDevices::get_connections_from_devices_( const size_t requested_source_node_id, +TargetTableDevices::get_connections_from_devices_( const size_t requested_source_node_id, const size_t requested_target_node_id, const size_t tid, const synindex syn_id, @@ -181,7 +185,7 @@ nest::TargetTableDevices::get_connections_from_devices_( const size_t requested_ } void -nest::TargetTableDevices::get_connections( const size_t requested_source_node_id, +TargetTableDevices::get_connections( const size_t requested_source_node_id, const size_t requested_target_node_id, const size_t tid, const synindex syn_id, @@ -195,3 +199,46 @@ nest::TargetTableDevices::get_connections( const size_t requested_source_node_id get_connections_from_devices_( requested_source_node_id, requested_target_node_id, tid, syn_id, synapse_label, conns ); } + +void +TargetTableDevices::add_connection_to_device( Node& source, + Node& target, + const size_t source_node_id, + const size_t tid, + const synindex syn_id, + const DictionaryDatum& p, + const double d, + const double w ) +{ + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + assert( lid < target_to_devices_[ tid ].size() ); + assert( syn_id < target_to_devices_[ tid ][ lid ].size() ); + + kernel() + .model_manager.get_connection_model( syn_id, tid ) + .add_connection( source, target, target_to_devices_[ tid ][ lid ], syn_id, p, d, w ); +} + +void +TargetTableDevices::add_connection_from_device( Node& source, + Node& target, + const size_t tid, + const synindex syn_id, + const DictionaryDatum& p, + const double d, + const double w ) +{ + const size_t ldid = source.get_local_device_id(); + assert( ldid != invalid_index ); + assert( ldid < target_from_devices_[ tid ].size() ); + assert( syn_id < target_from_devices_[ tid ][ ldid ].size() ); + + kernel() + .model_manager.get_connection_model( syn_id, tid ) + .add_connection( source, target, target_from_devices_[ tid ][ ldid ], syn_id, p, d, w ); + + // store node ID of sending device + sending_devices_node_ids_[ tid ][ ldid ] = source.get_node_id(); +} + +} diff --git a/nestkernel/target_table_devices.h b/nestkernel/target_table_devices.h index de6d31db3d..6d72f42ad3 100644 --- a/nestkernel/target_table_devices.h +++ b/nestkernel/target_table_devices.h @@ -24,18 +24,16 @@ #define TARGET_TABLE_DEVICES_H // C++ includes: -#include -#include #include // Includes from nestkernel: #include "connection_id.h" #include "connector_base.h" #include "event.h" +#include "kernel_manager.h" #include "nest_types.h" // Includes from SLI: -#include "arraydatum.h" #include "dictdatum.h" namespace nest @@ -264,6 +262,68 @@ TargetTableDevices::is_device_connected( const size_t tid, const size_t lcid ) c return false; } +inline void +TargetTableDevices::send_to_device( const size_t tid, + const size_t source_node_id, + Event& e, + const std::vector< ConnectorModel* >& cm ) +{ + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + for ( std::vector< ConnectorBase* >::iterator it = target_to_devices_[ tid ][ lid ].begin(); + it != target_to_devices_[ tid ][ lid ].end(); + ++it ) + { + if ( *it ) + { + ( *it )->send_to_all( tid, cm, e ); + } + } +} + +inline void +TargetTableDevices::send_to_device( const size_t tid, + const size_t source_node_id, + SecondaryEvent& e, + const std::vector< ConnectorModel* >& cm ) +{ + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + for ( auto& synid : e.get_supported_syn_ids() ) + { + if ( target_to_devices_[ tid ][ lid ][ synid ] ) + { + target_to_devices_[ tid ][ lid ][ synid ]->send_to_all( tid, cm, e ); + } + } +} + +inline void +TargetTableDevices::get_synapse_status_to_device( const size_t tid, + const size_t source_node_id, + const synindex syn_id, + DictionaryDatum& dict, + const size_t lcid ) const +{ + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + if ( target_to_devices_[ tid ][ lid ][ syn_id ] ) + { + target_to_devices_[ tid ][ lid ][ syn_id ]->get_synapse_status( tid, lcid, dict ); + } +} + +inline void +TargetTableDevices::set_synapse_status_to_device( const size_t tid, + const size_t source_node_id, + const synindex syn_id, + ConnectorModel& cm, + const DictionaryDatum& dict, + const size_t lcid ) +{ + const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); + if ( target_to_devices_[ tid ][ lid ][ syn_id ] ) + { + target_to_devices_[ tid ][ lid ][ syn_id ]->set_synapse_status( lcid, dict, cm ); + } +} } // namespace nest diff --git a/nestkernel/target_table_devices_impl.h b/nestkernel/target_table_devices_impl.h deleted file mode 100644 index 26a4668fb1..0000000000 --- a/nestkernel/target_table_devices_impl.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * target_table_devices_impl.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 TARGET_TABLE_DEVICES_IMPL_H -#define TARGET_TABLE_DEVICES_IMPL_H - -// Includes from nestkernel: -#include "connector_base.h" -#include "kernel_manager.h" -#include "model_manager.h" -#include "node.h" -#include "target_table_devices.h" -#include "vp_manager_impl.h" - -inline void -nest::TargetTableDevices::add_connection_to_device( Node& source, - Node& target, - const size_t source_node_id, - const size_t tid, - const synindex syn_id, - const DictionaryDatum& p, - const double d, - const double w ) -{ - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - assert( lid < target_to_devices_[ tid ].size() ); - assert( syn_id < target_to_devices_[ tid ][ lid ].size() ); - - kernel() - .model_manager.get_connection_model( syn_id, tid ) - .add_connection( source, target, target_to_devices_[ tid ][ lid ], syn_id, p, d, w ); -} - -inline void -nest::TargetTableDevices::add_connection_from_device( Node& source, - Node& target, - const size_t tid, - const synindex syn_id, - const DictionaryDatum& p, - const double d, - const double w ) -{ - const size_t ldid = source.get_local_device_id(); - assert( ldid != invalid_index ); - assert( ldid < target_from_devices_[ tid ].size() ); - assert( syn_id < target_from_devices_[ tid ][ ldid ].size() ); - - kernel() - .model_manager.get_connection_model( syn_id, tid ) - .add_connection( source, target, target_from_devices_[ tid ][ ldid ], syn_id, p, d, w ); - - // store node ID of sending device - sending_devices_node_ids_[ tid ][ ldid ] = source.get_node_id(); -} - -inline void -nest::TargetTableDevices::send_to_device( const size_t tid, - const size_t source_node_id, - Event& e, - const std::vector< ConnectorModel* >& cm ) -{ - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - for ( std::vector< ConnectorBase* >::iterator it = target_to_devices_[ tid ][ lid ].begin(); - it != target_to_devices_[ tid ][ lid ].end(); - ++it ) - { - if ( *it ) - { - ( *it )->send_to_all( tid, cm, e ); - } - } -} - -inline void -nest::TargetTableDevices::send_to_device( const size_t tid, - const size_t source_node_id, - SecondaryEvent& e, - const std::vector< ConnectorModel* >& cm ) -{ - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - for ( auto& synid : e.get_supported_syn_ids() ) - { - if ( target_to_devices_[ tid ][ lid ][ synid ] ) - { - target_to_devices_[ tid ][ lid ][ synid ]->send_to_all( tid, cm, e ); - } - } -} - -inline void -nest::TargetTableDevices::get_synapse_status_to_device( const size_t tid, - const size_t source_node_id, - const synindex syn_id, - DictionaryDatum& dict, - const size_t lcid ) const -{ - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - if ( target_to_devices_[ tid ][ lid ][ syn_id ] ) - { - target_to_devices_[ tid ][ lid ][ syn_id ]->get_synapse_status( tid, lcid, dict ); - } -} - -inline void -nest::TargetTableDevices::set_synapse_status_to_device( const size_t tid, - const size_t source_node_id, - const synindex syn_id, - ConnectorModel& cm, - const DictionaryDatum& dict, - const size_t lcid ) -{ - const size_t lid = kernel().vp_manager.node_id_to_lid( source_node_id ); - if ( target_to_devices_[ tid ][ lid ][ syn_id ] ) - { - target_to_devices_[ tid ][ lid ][ syn_id ]->set_synapse_status( lcid, dict, cm ); - } -} - -#endif /* TARGET_TABLE_DEVICES_IMPL_H */ diff --git a/nestkernel/universal_data_logger.h b/nestkernel/universal_data_logger.h index cb51337b12..f78bf95be7 100644 --- a/nestkernel/universal_data_logger.h +++ b/nestkernel/universal_data_logger.h @@ -29,8 +29,10 @@ // Includes from nestkernel: #include "event.h" +#include "event_delivery_manager.h" +#include "kernel_manager.h" #include "nest_time.h" -#include "nest_types.h" +#include "node.h" #include "recordables_map.h" namespace nest @@ -84,27 +86,21 @@ namespace nest * * ... * - * nest::iaf_cond_alpha::Buffers_::Buffers_(iaf_cond_alpha& n) + * iaf_cond_alpha::Buffers_::Buffers_(iaf_cond_alpha& n) * : logger_(n), ... {} * - * nest::iaf_cond_alpha::Buffers_::Buffers_(const Buffers_&, iaf_cond_alpha& n) + * iaf_cond_alpha::Buffers_::Buffers_(const Buffers_&, iaf_cond_alpha& n) * : logger_(n), ... {} * - * nest::iaf_cond_alpha::iaf_cond_alpha() + * iaf_cond_alpha::iaf_cond_alpha() * : ..., B_(*this) {} * - * nest::iaf_cond_alpha::iaf_cond_alpha(const iaf_cond_alpha& n) + * iaf_cond_alpha::iaf_cond_alpha(const iaf_cond_alpha& n) * : ..., B_(n.B_, *this) {} * @code * * @todo Could HostNode be passed as const& to handle() and record_data()? * - * @note To avoid inclusion problems and code-bloat, the class - * interface is defined in this file, while most of the - * implementation is in the companion universal_data_logger_impl.h. - * As a consequence, calls to UniversalDataLogger members should - * only come from cpp files---do not inline them. - * * @addtogroup Devices */ @@ -235,7 +231,7 @@ class UniversalDataLogger // which typically is in h-files. template < typename HostNode > size_t -nest::UniversalDataLogger< HostNode >::connect_logging_device( const DataLoggingRequest& req, +UniversalDataLogger< HostNode >::connect_logging_device( const DataLoggingRequest& req, const RecordablesMap< HostNode >& rmap ) { // rports are assigned consecutively, the caller may not request specific @@ -266,7 +262,7 @@ nest::UniversalDataLogger< HostNode >::connect_logging_device( const DataLogging } template < typename HostNode > -nest::UniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const DataLoggingRequest& req, +UniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const DataLoggingRequest& req, const RecordablesMap< HostNode >& rmap ) : multimeter_( req.get_sender().get_node_id() ) , num_vars_( 0 ) @@ -342,30 +338,24 @@ nest::UniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const DataLoggi * * ... * - * nest::aeif_cond_beta_multisynapse::Buffers_::Buffers_(aeif_cond_beta_multisynapse& + * aeif_cond_beta_multisynapse::Buffers_::Buffers_(aeif_cond_beta_multisynapse& * n) * : logger_(n), ... {} * - * nest::aeif_cond_beta_multisynapse::Buffers_::Buffers_(const Buffers_&, + * aeif_cond_beta_multisynapse::Buffers_::Buffers_(const Buffers_&, * aeif_cond_beta_multisynapse& n) * : logger_(n), ... {} * - * nest::aeif_cond_beta_multisynapse::aeif_cond_beta_multisynapse() + * aeif_cond_beta_multisynapse::aeif_cond_beta_multisynapse() * : ..., B_(*this) {} * - * nest::aeif_cond_beta_multisynapse::aeif_cond_beta_multisynapse(const + * aeif_cond_beta_multisynapse::aeif_cond_beta_multisynapse(const * aeif_cond_beta_multisynapse& n) * : ..., B_(n.B_, *this) {} * @code * * @todo Could HostNode be passed as const& to handle() and record_data()? * - * @note To avoid inclusion problems and code-bloat, the class - * interface is defined in this file, while most of the - * implementation is in the companion universal_data_logger_impl.h. - * As a consequence, calls to UniversalDataLogger members should - * only come from cpp files---do not inline them. - * * @addtogroup Devices */ @@ -497,7 +487,7 @@ class DynamicUniversalDataLogger // which typically is in h-files. template < typename HostNode > size_t -nest::DynamicUniversalDataLogger< HostNode >::connect_logging_device( const DataLoggingRequest& req, +DynamicUniversalDataLogger< HostNode >::connect_logging_device( const DataLoggingRequest& req, const DynamicRecordablesMap< HostNode >& rmap ) { // rports are assigned consecutively, the caller may not request specific @@ -529,7 +519,7 @@ nest::DynamicUniversalDataLogger< HostNode >::connect_logging_device( const Data } template < typename HostNode > -nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const DataLoggingRequest& req, +DynamicUniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const DataLoggingRequest& req, const DynamicRecordablesMap< HostNode >& rmap ) : multimeter_( req.get_sender().get_node_id() ) , num_vars_( 0 ) @@ -570,6 +560,408 @@ nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::DataLogger_( const Da recording_offset_ = req.get_recording_offset(); } +template < typename HostNode > +DynamicUniversalDataLogger< HostNode >::DynamicUniversalDataLogger( HostNode& host ) + : host_( host ) + , data_loggers_() +{ +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::reset() +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->reset(); + } +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::init() +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->init(); + } +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::record_data( long step ) +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->record_data( host_, step ); + } +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::handle( const DataLoggingRequest& dlr ) +{ + const size_t rport = dlr.get_rport(); + assert( rport >= 1 ); + assert( static_cast< size_t >( rport ) <= data_loggers_.size() ); + data_loggers_[ rport - 1 ].handle( host_, dlr ); +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::DataLogger_::reset() +{ + data_.clear(); + next_rec_step_ = -1; // flag as uninitialized +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::DataLogger_::init() +{ + if ( num_vars_ < 1 ) + { + return; + } // not recording anything + + // Next recording step is in current slice or beyond, indicates that + // buffer is properly initialized. + if ( next_rec_step_ >= kernel().simulation_manager.get_slice_origin().get_steps() ) + { + return; + } + + // If we get here, the buffer has either never been initialized or has been dormant + // during a period when the host node was frozen. We then (re-)initialize. + data_.clear(); + + // store recording time in steps + rec_int_steps_ = recording_interval_.get_steps(); + + // set next recording step to first multiple of rec_int_steps_ + // beyond current time, shifted one to left, since rec_step marks + // left of update intervals, and we want time stamps at right end of + // update interval to be multiples of recording interval. Need to add + // +1 because the division result is rounded down. + next_rec_step_ = ( kernel().simulation_manager.get_time().get_steps() / rec_int_steps_ + 1 ) * rec_int_steps_ - 1; + + // If offset is not 0, adjust next recording step to account for it by first setting next recording + // step to be offset and then iterating until the variable is greater than current simulation time. + if ( recording_offset_.get_steps() != 0 ) + { + next_rec_step_ = recording_offset_.get_steps() - 1; // shifted one to left + while ( next_rec_step_ <= kernel().simulation_manager.get_time().get_steps() ) + { + next_rec_step_ += rec_int_steps_; + } + } + + // number of data points per slice + const long recs_per_slice = static_cast< long >( + std::ceil( kernel().connection_manager.get_min_delay() / static_cast< double >( rec_int_steps_ ) ) ); + + data_.resize( 2, DataLoggingReply::Container( recs_per_slice, DataLoggingReply::Item( num_vars_ ) ) ); + + next_rec_.resize( 2 ); // just for safety's sake + next_rec_[ 0 ] = next_rec_[ 1 ] = 0; // start at beginning of buffer +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::DataLogger_::record_data( const HostNode&, long step ) +{ + if ( num_vars_ < 1 or step < next_rec_step_ ) + { + return; + } + + const size_t wt = kernel().event_delivery_manager.write_toggle(); + + assert( wt < next_rec_.size() ); + assert( wt < data_.size() ); + + // The following assertion may fire if the multimeter connected to + // this logger is frozen. In that case, handle() is not called and + // next_rec_[wt] never reset. The assert() prevents error propagation. + // This is not an exception, since I consider the chance of users + // freezing multimeters very slim. + // See #464 for details. + assert( next_rec_[ wt ] < data_[ wt ].size() ); + + DataLoggingReply::Item& dest = data_[ wt ][ next_rec_[ wt ] ]; + + // set time stamp: step is left end of update interval, so add 1 + dest.timestamp = Time::step( step + 1 ); + + // obtain data through access functions, calling via pointer-to-member + for ( size_t j = 0; j < num_vars_; ++j ) + { + dest.data[ j ] = ( *( node_access_[ j ] ) )(); + } + + next_rec_step_ += rec_int_steps_; + + // We just increment. Construction ensures that we cannot overflow, + // and read-out resets. + // Overflow is possible if the multimeter is frozen, see #464. + // In that case, the assertion above will trigger. + ++next_rec_[ wt ]; +} + +template < typename HostNode > +void +DynamicUniversalDataLogger< HostNode >::DataLogger_::handle( HostNode& host, const DataLoggingRequest& request ) +{ + if ( num_vars_ < 1 ) + { + return; + } // nothing to do + + // The following assertions will fire if the user forgot to call init() + // on the data logger. + assert( next_rec_.size() == 2 ); + assert( data_.size() == 2 ); + + // get read toggle and start and end of slice + const size_t rt = kernel().event_delivery_manager.read_toggle(); + assert( not data_[ rt ].empty() ); + + // Check if we have valid data, i.e., data with time stamps within the + // past time slice. This may not be the case if the node has been frozen. + // In that case, we still reset the recording marker, to prepare for the next round. + if ( data_[ rt ][ 0 ].timestamp <= kernel().simulation_manager.get_previous_slice_origin() ) + { + next_rec_[ rt ] = 0; + return; + } + + // If recording interval and min_delay are not commensurable, + // the last entry of data_ will not contain useful data for every + // other slice. We mark this by time stamp -infinity. + // Applying this mark here is less work than initializing all time stamps + // to -infinity after each call to this function. + if ( next_rec_[ rt ] < data_[ rt ].size() ) + { + data_[ rt ][ next_rec_[ rt ] ].timestamp = Time::neg_inf(); + } + + // now create reply event and rigg it + DataLoggingReply reply( data_[ rt ] ); + + // "clear" data + next_rec_[ rt ] = 0; + + reply.set_sender( host ); + reply.set_sender_node_id( host.get_node_id() ); + reply.set_receiver( request.get_sender() ); + reply.set_port( request.get_port() ); + + // send it off + kernel().event_delivery_manager.send_to_node( reply ); +} + +template < typename HostNode > +UniversalDataLogger< HostNode >::UniversalDataLogger( HostNode& host ) + : host_( host ) + , data_loggers_() +{ +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::reset() +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->reset(); + } +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::init() +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->init(); + } +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::record_data( long step ) +{ + for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) + { + it->record_data( host_, step ); + } +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::handle( const DataLoggingRequest& dlr ) +{ + const size_t rport = dlr.get_rport(); + assert( rport >= 1 ); + assert( static_cast< size_t >( rport ) <= data_loggers_.size() ); + data_loggers_[ rport - 1 ].handle( host_, dlr ); +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::DataLogger_::reset() +{ + data_.clear(); + next_rec_step_ = -1; // flag as uninitialized +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::DataLogger_::init() +{ + if ( num_vars_ < 1 ) + { + // not recording anything + return; + } + + // Next recording step is in current slice or beyond, indicates that + // buffer is properly initialized. + if ( next_rec_step_ >= kernel().simulation_manager.get_slice_origin().get_steps() ) + { + return; + } + + // If we get here, the buffer has either never been initialized or has + // been dormant during a period when the host node was frozen. We then (re-)initialize. + data_.clear(); + + // store recording time in steps + rec_int_steps_ = recording_interval_.get_steps(); + + // set next recording step to first multiple of rec_int_steps_ + // beyond current time, shifted one to left, since rec_step marks + // left of update intervals, and we want time stamps at right end of + // update interval to be multiples of recording interval. Need to add + // +1 because the division result is rounded down. + next_rec_step_ = ( kernel().simulation_manager.get_time().get_steps() / rec_int_steps_ + 1 ) * rec_int_steps_ - 1; + + // If offset is not 0, adjust next recording step to account for it by first setting next recording + // step to be offset and then iterating until the variable is greater than current simulation time. + if ( recording_offset_.get_steps() != 0 ) + { + next_rec_step_ = recording_offset_.get_steps() - 1; // shifted one to left + while ( next_rec_step_ <= kernel().simulation_manager.get_time().get_steps() ) + { + next_rec_step_ += rec_int_steps_; + } + } + + // number of data points per slice + const long recs_per_slice = static_cast< long >( + std::ceil( kernel().connection_manager.get_min_delay() / static_cast< double >( rec_int_steps_ ) ) ); + + data_.resize( 2, DataLoggingReply::Container( recs_per_slice, DataLoggingReply::Item( num_vars_ ) ) ); + + next_rec_.resize( 2 ); // just for safety's sake + next_rec_[ 0 ] = next_rec_[ 1 ] = 0; // start at beginning of buffer +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::DataLogger_::record_data( const HostNode& host, long step ) +{ + if ( num_vars_ < 1 or step < next_rec_step_ ) + { + return; + } + + const size_t wt = kernel().event_delivery_manager.write_toggle(); + + assert( wt < next_rec_.size() ); + assert( wt < data_.size() ); + + // The following assertion may fire if the multimeter connected to + // this logger is frozen. In that case, handle() is not called and + // next_rec_[wt] never reset. The assert() prevents error propagation. + // This is not an exception, since I consider the chance of users + // freezing multimeters very slim. + // See #464 for details. + assert( next_rec_[ wt ] < data_[ wt ].size() ); + + DataLoggingReply::Item& dest = data_[ wt ][ next_rec_[ wt ] ]; + + // set time stamp: step is left end of update interval, so add 1 + dest.timestamp = Time::step( step + 1 ); + + // obtain data through access functions, calling via pointer-to-member + for ( size_t j = 0; j < num_vars_; ++j ) + { + dest.data[ j ] = ( ( host ).*( node_access_[ j ] ) )(); + } + + next_rec_step_ += rec_int_steps_; + + // We just increment. Construction ensures that we cannot overflow, + // and read-out resets. + // Overflow is possible if the multimeter is frozen, see #464. + // In that case, the assertion above will trigger. + ++next_rec_[ wt ]; +} + +template < typename HostNode > +void +UniversalDataLogger< HostNode >::DataLogger_::handle( HostNode& host, const DataLoggingRequest& request ) +{ + if ( num_vars_ < 1 ) + { + // nothing to do + return; + } + + // The following assertions will fire if the user forgot to call init() + // on the data logger. + assert( next_rec_.size() == 2 ); + assert( data_.size() == 2 ); + + // get read toggle and start and end of slice + const size_t rt = kernel().event_delivery_manager.read_toggle(); + assert( not data_[ rt ].empty() ); + + // Check if we have valid data, i.e., data with time stamps within the + // past time slice. This may not be the case if the node has been frozen. + // In that case, we still reset the recording marker, to prepare for the next round. + if ( data_[ rt ][ 0 ].timestamp <= kernel().simulation_manager.get_previous_slice_origin() ) + { + next_rec_[ rt ] = 0; + return; + } + + // If recording interval and min_delay are not commensurable, + // the last entry of data_ will not contain useful data for every + // other slice. We mark this by time stamp -infinity. + // Applying this mark here is less work than initializing all time stamps + // to -infinity after each call to this function. + if ( next_rec_[ rt ] < data_[ rt ].size() ) + { + data_[ rt ][ next_rec_[ rt ] ].timestamp = Time::neg_inf(); + } + + // now create reply event and rigg it + DataLoggingReply reply( data_[ rt ] ); + + // "clear" data + next_rec_[ rt ] = 0; + + reply.set_sender( host ); + reply.set_sender_node_id( host.get_node_id() ); + reply.set_receiver( request.get_sender() ); + reply.set_port( request.get_port() ); + + // send it off + kernel().event_delivery_manager.send_to_node( reply ); +} + } // namespace nest #endif /* #ifndef UNIVERSAL_DATA_LOGGER_H */ diff --git a/nestkernel/universal_data_logger_impl.h b/nestkernel/universal_data_logger_impl.h deleted file mode 100644 index 8b22da5872..0000000000 --- a/nestkernel/universal_data_logger_impl.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * universal_data_logger_impl.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 UNIVERSAL_DATA_LOGGER_IMPL_H -#define UNIVERSAL_DATA_LOGGER_IMPL_H - -#include "universal_data_logger.h" - -// Includes from nestkernel: -#include "event_delivery_manager_impl.h" -#include "kernel_manager.h" -#include "nest_time.h" -#include "node.h" - -template < typename HostNode > -nest::DynamicUniversalDataLogger< HostNode >::DynamicUniversalDataLogger( HostNode& host ) - : host_( host ) - , data_loggers_() -{ -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::reset() -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->reset(); - } -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::init() -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->init(); - } -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::record_data( long step ) -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->record_data( host_, step ); - } -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::handle( const DataLoggingRequest& dlr ) -{ - const size_t rport = dlr.get_rport(); - assert( rport >= 1 ); - assert( static_cast< size_t >( rport ) <= data_loggers_.size() ); - data_loggers_[ rport - 1 ].handle( host_, dlr ); -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::reset() -{ - data_.clear(); - next_rec_step_ = -1; // flag as uninitialized -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::init() -{ - if ( num_vars_ < 1 ) - { - return; - } // not recording anything - - // Next recording step is in current slice or beyond, indicates that - // buffer is properly initialized. - if ( next_rec_step_ >= kernel().simulation_manager.get_slice_origin().get_steps() ) - { - return; - } - - // If we get here, the buffer has either never been initialized or has been dormant - // during a period when the host node was frozen. We then (re-)initialize. - data_.clear(); - - // store recording time in steps - rec_int_steps_ = recording_interval_.get_steps(); - - // set next recording step to first multiple of rec_int_steps_ - // beyond current time, shifted one to left, since rec_step marks - // left of update intervals, and we want time stamps at right end of - // update interval to be multiples of recording interval. Need to add - // +1 because the division result is rounded down. - next_rec_step_ = ( kernel().simulation_manager.get_time().get_steps() / rec_int_steps_ + 1 ) * rec_int_steps_ - 1; - - // If offset is not 0, adjust next recording step to account for it by first setting next recording - // step to be offset and then iterating until the variable is greater than current simulation time. - if ( recording_offset_.get_steps() != 0 ) - { - next_rec_step_ = recording_offset_.get_steps() - 1; // shifted one to left - while ( next_rec_step_ <= kernel().simulation_manager.get_time().get_steps() ) - { - next_rec_step_ += rec_int_steps_; - } - } - - // number of data points per slice - const long recs_per_slice = static_cast< long >( - std::ceil( kernel().connection_manager.get_min_delay() / static_cast< double >( rec_int_steps_ ) ) ); - - data_.resize( 2, DataLoggingReply::Container( recs_per_slice, DataLoggingReply::Item( num_vars_ ) ) ); - - next_rec_.resize( 2 ); // just for safety's sake - next_rec_[ 0 ] = next_rec_[ 1 ] = 0; // start at beginning of buffer -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::record_data( const HostNode&, long step ) -{ - if ( num_vars_ < 1 or step < next_rec_step_ ) - { - return; - } - - const size_t wt = kernel().event_delivery_manager.write_toggle(); - - assert( wt < next_rec_.size() ); - assert( wt < data_.size() ); - - // The following assertion may fire if the multimeter connected to - // this logger is frozen. In that case, handle() is not called and - // next_rec_[wt] never reset. The assert() prevents error propagation. - // This is not an exception, since I consider the chance of users - // freezing multimeters very slim. - // See #464 for details. - assert( next_rec_[ wt ] < data_[ wt ].size() ); - - DataLoggingReply::Item& dest = data_[ wt ][ next_rec_[ wt ] ]; - - // set time stamp: step is left end of update interval, so add 1 - dest.timestamp = Time::step( step + 1 ); - - // obtain data through access functions, calling via pointer-to-member - for ( size_t j = 0; j < num_vars_; ++j ) - { - dest.data[ j ] = ( *( node_access_[ j ] ) )(); - } - - next_rec_step_ += rec_int_steps_; - - // We just increment. Construction ensures that we cannot overflow, - // and read-out resets. - // Overflow is possible if the multimeter is frozen, see #464. - // In that case, the assertion above will trigger. - ++next_rec_[ wt ]; -} - -template < typename HostNode > -void -nest::DynamicUniversalDataLogger< HostNode >::DataLogger_::handle( HostNode& host, const DataLoggingRequest& request ) -{ - if ( num_vars_ < 1 ) - { - return; - } // nothing to do - - // The following assertions will fire if the user forgot to call init() - // on the data logger. - assert( next_rec_.size() == 2 ); - assert( data_.size() == 2 ); - - // get read toggle and start and end of slice - const size_t rt = kernel().event_delivery_manager.read_toggle(); - assert( not data_[ rt ].empty() ); - - // Check if we have valid data, i.e., data with time stamps within the - // past time slice. This may not be the case if the node has been frozen. - // In that case, we still reset the recording marker, to prepare for the next round. - if ( data_[ rt ][ 0 ].timestamp <= kernel().simulation_manager.get_previous_slice_origin() ) - { - next_rec_[ rt ] = 0; - return; - } - - // If recording interval and min_delay are not commensurable, - // the last entry of data_ will not contain useful data for every - // other slice. We mark this by time stamp -infinity. - // Applying this mark here is less work than initializing all time stamps - // to -infinity after each call to this function. - if ( next_rec_[ rt ] < data_[ rt ].size() ) - { - data_[ rt ][ next_rec_[ rt ] ].timestamp = Time::neg_inf(); - } - - // now create reply event and rigg it - DataLoggingReply reply( data_[ rt ] ); - - // "clear" data - next_rec_[ rt ] = 0; - - reply.set_sender( host ); - reply.set_sender_node_id( host.get_node_id() ); - reply.set_receiver( request.get_sender() ); - reply.set_port( request.get_port() ); - - // send it off - kernel().event_delivery_manager.send_to_node( reply ); -} - -template < typename HostNode > -nest::UniversalDataLogger< HostNode >::UniversalDataLogger( HostNode& host ) - : host_( host ) - , data_loggers_() -{ -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::reset() -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->reset(); - } -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::init() -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->init(); - } -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::record_data( long step ) -{ - for ( DLiter_ it = data_loggers_.begin(); it != data_loggers_.end(); ++it ) - { - it->record_data( host_, step ); - } -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::handle( const DataLoggingRequest& dlr ) -{ - const size_t rport = dlr.get_rport(); - assert( rport >= 1 ); - assert( static_cast< size_t >( rport ) <= data_loggers_.size() ); - data_loggers_[ rport - 1 ].handle( host_, dlr ); -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::DataLogger_::reset() -{ - data_.clear(); - next_rec_step_ = -1; // flag as uninitialized -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::DataLogger_::init() -{ - if ( num_vars_ < 1 ) - { - // not recording anything - return; - } - - // Next recording step is in current slice or beyond, indicates that - // buffer is properly initialized. - if ( next_rec_step_ >= kernel().simulation_manager.get_slice_origin().get_steps() ) - { - return; - } - - // If we get here, the buffer has either never been initialized or has - // been dormant during a period when the host node was frozen. We then (re-)initialize. - data_.clear(); - - // store recording time in steps - rec_int_steps_ = recording_interval_.get_steps(); - - // set next recording step to first multiple of rec_int_steps_ - // beyond current time, shifted one to left, since rec_step marks - // left of update intervals, and we want time stamps at right end of - // update interval to be multiples of recording interval. Need to add - // +1 because the division result is rounded down. - next_rec_step_ = ( kernel().simulation_manager.get_time().get_steps() / rec_int_steps_ + 1 ) * rec_int_steps_ - 1; - - // If offset is not 0, adjust next recording step to account for it by first setting next recording - // step to be offset and then iterating until the variable is greater than current simulation time. - if ( recording_offset_.get_steps() != 0 ) - { - next_rec_step_ = recording_offset_.get_steps() - 1; // shifted one to left - while ( next_rec_step_ <= kernel().simulation_manager.get_time().get_steps() ) - { - next_rec_step_ += rec_int_steps_; - } - } - - // number of data points per slice - const long recs_per_slice = static_cast< long >( - std::ceil( kernel().connection_manager.get_min_delay() / static_cast< double >( rec_int_steps_ ) ) ); - - data_.resize( 2, DataLoggingReply::Container( recs_per_slice, DataLoggingReply::Item( num_vars_ ) ) ); - - next_rec_.resize( 2 ); // just for safety's sake - next_rec_[ 0 ] = next_rec_[ 1 ] = 0; // start at beginning of buffer -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::DataLogger_::record_data( const HostNode& host, long step ) -{ - if ( num_vars_ < 1 or step < next_rec_step_ ) - { - return; - } - - const size_t wt = kernel().event_delivery_manager.write_toggle(); - - assert( wt < next_rec_.size() ); - assert( wt < data_.size() ); - - // The following assertion may fire if the multimeter connected to - // this logger is frozen. In that case, handle() is not called and - // next_rec_[wt] never reset. The assert() prevents error propagation. - // This is not an exception, since I consider the chance of users - // freezing multimeters very slim. - // See #464 for details. - assert( next_rec_[ wt ] < data_[ wt ].size() ); - - DataLoggingReply::Item& dest = data_[ wt ][ next_rec_[ wt ] ]; - - // set time stamp: step is left end of update interval, so add 1 - dest.timestamp = Time::step( step + 1 ); - - // obtain data through access functions, calling via pointer-to-member - for ( size_t j = 0; j < num_vars_; ++j ) - { - dest.data[ j ] = ( ( host ).*( node_access_[ j ] ) )(); - } - - next_rec_step_ += rec_int_steps_; - - // We just increment. Construction ensures that we cannot overflow, - // and read-out resets. - // Overflow is possible if the multimeter is frozen, see #464. - // In that case, the assertion above will trigger. - ++next_rec_[ wt ]; -} - -template < typename HostNode > -void -nest::UniversalDataLogger< HostNode >::DataLogger_::handle( HostNode& host, const DataLoggingRequest& request ) -{ - if ( num_vars_ < 1 ) - { - // nothing to do - return; - } - - // The following assertions will fire if the user forgot to call init() - // on the data logger. - assert( next_rec_.size() == 2 ); - assert( data_.size() == 2 ); - - // get read toggle and start and end of slice - const size_t rt = kernel().event_delivery_manager.read_toggle(); - assert( not data_[ rt ].empty() ); - - // Check if we have valid data, i.e., data with time stamps within the - // past time slice. This may not be the case if the node has been frozen. - // In that case, we still reset the recording marker, to prepare for the next round. - if ( data_[ rt ][ 0 ].timestamp <= kernel().simulation_manager.get_previous_slice_origin() ) - { - next_rec_[ rt ] = 0; - return; - } - - // If recording interval and min_delay are not commensurable, - // the last entry of data_ will not contain useful data for every - // other slice. We mark this by time stamp -infinity. - // Applying this mark here is less work than initializing all time stamps - // to -infinity after each call to this function. - if ( next_rec_[ rt ] < data_[ rt ].size() ) - { - data_[ rt ][ next_rec_[ rt ] ].timestamp = Time::neg_inf(); - } - - // now create reply event and rigg it - DataLoggingReply reply( data_[ rt ] ); - - // "clear" data - next_rec_[ rt ] = 0; - - reply.set_sender( host ); - reply.set_sender_node_id( host.get_node_id() ); - reply.set_receiver( request.get_sender() ); - reply.set_port( request.get_port() ); - - // send it off - kernel().event_delivery_manager.send_to_node( reply ); -} - -#endif /* #ifndef UNIVERSAL_DATA_LOGGER_IMPL_H */ diff --git a/nestkernel/urbanczik_archiving_node.h b/nestkernel/urbanczik_archiving_node.h index a53e0f4ab7..40e6f418d1 100644 --- a/nestkernel/urbanczik_archiving_node.h +++ b/nestkernel/urbanczik_archiving_node.h @@ -143,6 +143,102 @@ UrbanczikArchivingNode< urbanczik_parameters >::get_tau_syn_in( int comp ) return urbanczik_params->tau_syn_in[ comp ]; } +template < class urbanczik_parameters > +UrbanczikArchivingNode< urbanczik_parameters >::UrbanczikArchivingNode() + : ArchivingNode() +{ +} + +template < class urbanczik_parameters > +UrbanczikArchivingNode< urbanczik_parameters >::UrbanczikArchivingNode( const UrbanczikArchivingNode& n ) + : ArchivingNode( n ) +{ +} + +template < class urbanczik_parameters > +void +UrbanczikArchivingNode< urbanczik_parameters >::get_status( DictionaryDatum& d ) const +{ + ArchivingNode::get_status( d ); +} + +template < class urbanczik_parameters > +void +UrbanczikArchivingNode< urbanczik_parameters >::set_status( const DictionaryDatum& d ) +{ + ArchivingNode::set_status( d ); +} + +template < class urbanczik_parameters > +void +UrbanczikArchivingNode< urbanczik_parameters >::get_urbanczik_history( double t1, + double t2, + std::deque< histentry_extended >::iterator* start, + std::deque< histentry_extended >::iterator* finish, + int comp ) +{ + *finish = urbanczik_history_[ comp - 1 ].end(); + if ( urbanczik_history_[ comp - 1 ].empty() ) + { + *start = *finish; + return; + } + else + { + std::deque< histentry_extended >::iterator runner = urbanczik_history_[ comp - 1 ].begin(); + // To have a well defined discretization of the integral, we make sure + // that we exclude the entry at t1 but include the one at t2 by subtracting + // a small number so that runner->t_ is never equal to t1 or t2. + while ( ( runner != urbanczik_history_[ comp - 1 ].end() ) and runner->t_ - 1.0e-6 < t1 ) + { + ++runner; + } + *start = runner; + while ( ( runner != urbanczik_history_[ comp - 1 ].end() ) and runner->t_ - 1.0e-6 < t2 ) + { + ( runner->access_counter_ )++; + ++runner; + } + *finish = runner; + } +} + +template < class urbanczik_parameters > +void +UrbanczikArchivingNode< urbanczik_parameters >::write_urbanczik_history( Time const& t_sp, + double V_W, + int n_spikes, + int comp ) +{ + const double t_ms = t_sp.get_ms(); + + const double g_D = urbanczik_params->g_conn[ urbanczik_parameters::SOMA ]; + const double g_L = urbanczik_params->g_L[ urbanczik_parameters::SOMA ]; + const double E_L = urbanczik_params->E_L[ urbanczik_parameters::SOMA ]; + const double V_W_star = ( ( E_L * g_L + V_W * g_D ) / ( g_D + g_L ) ); + + if ( n_incoming_ ) + { + // prune all entries from history which are no longer needed + // except the penultimate one. we might still need it. + while ( urbanczik_history_[ comp - 1 ].size() > 1 ) + { + if ( urbanczik_history_[ comp - 1 ].front().access_counter_ >= n_incoming_ ) + { + urbanczik_history_[ comp - 1 ].pop_front(); + } + else + { + break; + } + } + + double dPI = ( n_spikes - urbanczik_params->phi( V_W_star ) * Time::get_resolution().get_ms() ) + * urbanczik_params->h( V_W_star ); + urbanczik_history_[ comp - 1 ].push_back( histentry_extended( t_ms, dPI, 0 ) ); + } +} + } // namespace nest #endif /* #ifndef URBANCZIK_ARCHIVING_NODE_H */ diff --git a/nestkernel/urbanczik_archiving_node_impl.h b/nestkernel/urbanczik_archiving_node_impl.h deleted file mode 100644 index 62c105fff2..0000000000 --- a/nestkernel/urbanczik_archiving_node_impl.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * urbanczik_archiving_node_impl.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 . - * - */ - -#include "urbanczik_archiving_node.h" - -// Includes from nestkernel: -#include "kernel_manager.h" - -// Includes from sli: -#include "dictutils.h" - -namespace nest -{ - -// member functions for UrbanczikArchivingNode -template < class urbanczik_parameters > -nest::UrbanczikArchivingNode< urbanczik_parameters >::UrbanczikArchivingNode() - : ArchivingNode() -{ -} - -template < class urbanczik_parameters > -nest::UrbanczikArchivingNode< urbanczik_parameters >::UrbanczikArchivingNode( const UrbanczikArchivingNode& n ) - : ArchivingNode( n ) -{ -} - -template < class urbanczik_parameters > -void -nest::UrbanczikArchivingNode< urbanczik_parameters >::get_status( DictionaryDatum& d ) const -{ - ArchivingNode::get_status( d ); -} - -template < class urbanczik_parameters > -void -nest::UrbanczikArchivingNode< urbanczik_parameters >::set_status( const DictionaryDatum& d ) -{ - ArchivingNode::set_status( d ); -} - -template < class urbanczik_parameters > -void -nest::UrbanczikArchivingNode< urbanczik_parameters >::get_urbanczik_history( double t1, - double t2, - std::deque< histentry_extended >::iterator* start, - std::deque< histentry_extended >::iterator* finish, - int comp ) -{ - *finish = urbanczik_history_[ comp - 1 ].end(); - if ( urbanczik_history_[ comp - 1 ].empty() ) - { - *start = *finish; - return; - } - else - { - std::deque< histentry_extended >::iterator runner = urbanczik_history_[ comp - 1 ].begin(); - // To have a well defined discretization of the integral, we make sure - // that we exclude the entry at t1 but include the one at t2 by subtracting - // a small number so that runner->t_ is never equal to t1 or t2. - while ( ( runner != urbanczik_history_[ comp - 1 ].end() ) and runner->t_ - 1.0e-6 < t1 ) - { - ++runner; - } - *start = runner; - while ( ( runner != urbanczik_history_[ comp - 1 ].end() ) and runner->t_ - 1.0e-6 < t2 ) - { - ( runner->access_counter_ )++; - ++runner; - } - *finish = runner; - } -} - -template < class urbanczik_parameters > -void -nest::UrbanczikArchivingNode< urbanczik_parameters >::write_urbanczik_history( Time const& t_sp, - double V_W, - int n_spikes, - int comp ) -{ - const double t_ms = t_sp.get_ms(); - - const double g_D = urbanczik_params->g_conn[ urbanczik_parameters::SOMA ]; - const double g_L = urbanczik_params->g_L[ urbanczik_parameters::SOMA ]; - const double E_L = urbanczik_params->E_L[ urbanczik_parameters::SOMA ]; - const double V_W_star = ( ( E_L * g_L + V_W * g_D ) / ( g_D + g_L ) ); - - if ( n_incoming_ ) - { - // prune all entries from history which are no longer needed - // except the penultimate one. we might still need it. - while ( urbanczik_history_[ comp - 1 ].size() > 1 ) - { - if ( urbanczik_history_[ comp - 1 ].front().access_counter_ >= n_incoming_ ) - { - urbanczik_history_[ comp - 1 ].pop_front(); - } - else - { - break; - } - } - - double dPI = ( n_spikes - urbanczik_params->phi( V_W_star ) * Time::get_resolution().get_ms() ) - * urbanczik_params->h( V_W_star ); - urbanczik_history_[ comp - 1 ].push_back( histentry_extended( t_ms, dPI, 0 ) ); - } -} - -} // of namespace nest diff --git a/nestkernel/vp_manager.cpp b/nestkernel/vp_manager.cpp index 6ebf211e34..e9f3b21770 100644 --- a/nestkernel/vp_manager.cpp +++ b/nestkernel/vp_manager.cpp @@ -29,10 +29,13 @@ #include "logging.h" // Includes from nestkernel: +#include "connection_manager.h" #include "kernel_manager.h" +#include "logging_manager.h" +#include "model_manager.h" #include "mpi_manager.h" -#include "mpi_manager_impl.h" -#include "vp_manager_impl.h" +#include "node_manager.h" +#include "simulation_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/vp_manager.h b/nestkernel/vp_manager.h index c0acc819a0..597560f721 100644 --- a/nestkernel/vp_manager.h +++ b/nestkernel/vp_manager.h @@ -26,12 +26,11 @@ // Includes from libnestutil: #include "manager_interface.h" -// Includes from nestkernel: -#include "nest_types.h" - // Includes from sli: #include "dictdatum.h" +#include "mpi_manager.h" + #ifdef _OPENMP // C includes: #include @@ -90,6 +89,11 @@ class VPManager : public ManagerInterface */ size_t get_OMP_NUM_THREADS() const; + /* + * Return the process id of the node with the specified node ID. + */ + size_t get_process_id_of_node_id( const size_t node_id ) const; + /** * Returns true if the given global node exists on this vp. */ @@ -173,10 +177,9 @@ class VPManager : public ManagerInterface const bool force_singlethreading_; size_t n_threads_; //!< Number of threads per process. }; -} inline size_t -nest::VPManager::get_thread_id() const +VPManager::get_thread_id() const { #ifdef _OPENMP return omp_get_thread_num(); @@ -186,13 +189,13 @@ nest::VPManager::get_thread_id() const } inline size_t -nest::VPManager::get_num_threads() const +VPManager::get_num_threads() const { return n_threads_; } inline void -nest::VPManager::assert_single_threaded() const +VPManager::assert_single_threaded() const { #ifdef _OPENMP assert( omp_get_num_threads() == 1 ); @@ -200,7 +203,7 @@ nest::VPManager::assert_single_threaded() const } inline void -nest::VPManager::assert_thread_parallel() const +VPManager::assert_thread_parallel() const { #ifdef _OPENMP // omp_get_num_threads() returns int @@ -208,5 +211,119 @@ nest::VPManager::assert_thread_parallel() const #endif } +inline size_t +VPManager::get_vp() const +{ + return kernel().mpi_manager.get_rank() + get_thread_id() * kernel().mpi_manager.get_num_processes(); +} + +inline size_t +VPManager::node_id_to_vp( const size_t node_id ) const +{ + return node_id % get_num_virtual_processes(); +} + +inline size_t +VPManager::vp_to_thread( const size_t vp ) const +{ + return vp / kernel().mpi_manager.get_num_processes(); +} + +inline size_t +VPManager::get_num_virtual_processes() const +{ + return get_num_threads() * kernel().mpi_manager.get_num_processes(); +} + +inline bool +VPManager::is_local_vp( const size_t vp ) const +{ + return kernel().mpi_manager.get_process_id_of_vp( vp ) == kernel().mpi_manager.get_rank(); +} + +inline size_t +VPManager::thread_to_vp( const size_t tid ) const +{ + return tid * kernel().mpi_manager.get_num_processes() + kernel().mpi_manager.get_rank(); +} + +inline bool +VPManager::is_node_id_vp_local( const size_t node_id ) const +{ + return ( node_id % get_num_virtual_processes() == static_cast< size_t >( get_vp() ) ); +} + +inline size_t +VPManager::node_id_to_lid( const size_t node_id ) const +{ + // starts at lid 0 for node_ids >= 1 (expected value for neurons, excl. node ID 0) + return std::ceil( static_cast< double >( node_id ) / get_num_virtual_processes() ) - 1; +} + +inline size_t +VPManager::lid_to_node_id( const size_t lid ) const +{ + const size_t vp = get_vp(); + return ( lid + static_cast< size_t >( vp == 0 ) ) * get_num_virtual_processes() + vp; +} + +inline size_t +VPManager::get_num_assigned_ranks_per_thread() const +{ + return std::ceil( static_cast< double >( kernel().mpi_manager.get_num_processes() ) / n_threads_ ); +} + +inline size_t +VPManager::get_start_rank_per_thread( const size_t tid ) const +{ + return tid * get_num_assigned_ranks_per_thread(); +} + +inline size_t +VPManager::get_end_rank_per_thread( const size_t rank_start, const size_t num_assigned_ranks_per_thread ) const +{ + size_t rank_end = rank_start + num_assigned_ranks_per_thread; + + // if we have more threads than ranks, or if ranks can not be + // distributed evenly on threads, we need to make sure, that all + // threads care only about existing ranks + if ( rank_end > kernel().mpi_manager.get_num_processes() ) + { + rank_end = std::max( rank_start, kernel().mpi_manager.get_num_processes() ); + } + + return rank_end; +} + +inline AssignedRanks +VPManager::get_assigned_ranks( const size_t tid ) +{ + AssignedRanks assigned_ranks; + assigned_ranks.begin = get_start_rank_per_thread( tid ); + assigned_ranks.max_size = get_num_assigned_ranks_per_thread(); + assigned_ranks.end = get_end_rank_per_thread( assigned_ranks.begin, assigned_ranks.max_size ); + assigned_ranks.size = assigned_ranks.end - assigned_ranks.begin; + return assigned_ranks; +} + +#ifdef HAVE_MPI + +inline size_t +nest::VPManager::get_process_id_of_node_id( const size_t node_id ) const +{ + return node_id % get_num_virtual_processes() % kernel().mpi_manager.get_num_processes(); +} + +#else // HAVE_MPI + +inline size_t +nest::VPManager::get_process_id_of_node_id( const size_t ) const +{ + return 0; +} + +#endif /* HAVE_MPI */ + +} // namespace nest #endif /* #ifndef VP_MANAGER_H */ diff --git a/nestkernel/vp_manager_impl.h b/nestkernel/vp_manager_impl.h deleted file mode 100644 index e7fa701d3a..0000000000 --- a/nestkernel/vp_manager_impl.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * vp_manager_impl.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 VP_MANAGER_IMPL_H -#define VP_MANAGER_IMPL_H - -#include "vp_manager.h" - -// Includes from nestkernel: -#include "kernel_manager.h" -#include "mpi_manager.h" -#include "mpi_manager_impl.h" - -namespace nest -{ - -inline size_t -VPManager::get_vp() const -{ - return kernel().mpi_manager.get_rank() + get_thread_id() * kernel().mpi_manager.get_num_processes(); -} - -inline size_t -VPManager::node_id_to_vp( const size_t node_id ) const -{ - return node_id % get_num_virtual_processes(); -} - -inline size_t -VPManager::vp_to_thread( const size_t vp ) const -{ - return vp / kernel().mpi_manager.get_num_processes(); -} - -inline size_t -VPManager::get_num_virtual_processes() const -{ - return get_num_threads() * kernel().mpi_manager.get_num_processes(); -} - -inline bool -VPManager::is_local_vp( const size_t vp ) const -{ - return kernel().mpi_manager.get_process_id_of_vp( vp ) == kernel().mpi_manager.get_rank(); -} - -inline size_t -VPManager::thread_to_vp( const size_t tid ) const -{ - return tid * kernel().mpi_manager.get_num_processes() + kernel().mpi_manager.get_rank(); -} - -inline bool -VPManager::is_node_id_vp_local( const size_t node_id ) const -{ - return ( node_id % get_num_virtual_processes() == static_cast< size_t >( get_vp() ) ); -} - -inline size_t -VPManager::node_id_to_lid( const size_t node_id ) const -{ - // starts at lid 0 for node_ids >= 1 (expected value for neurons, excl. node ID 0) - return std::ceil( static_cast< double >( node_id ) / get_num_virtual_processes() ) - 1; -} - -inline size_t -VPManager::lid_to_node_id( const size_t lid ) const -{ - const size_t vp = get_vp(); - return ( lid + static_cast< size_t >( vp == 0 ) ) * get_num_virtual_processes() + vp; -} - -inline size_t -VPManager::get_num_assigned_ranks_per_thread() const -{ - return std::ceil( static_cast< double >( kernel().mpi_manager.get_num_processes() ) / n_threads_ ); -} - -inline size_t -VPManager::get_start_rank_per_thread( const size_t tid ) const -{ - return tid * get_num_assigned_ranks_per_thread(); -} - -inline size_t -VPManager::get_end_rank_per_thread( const size_t rank_start, const size_t num_assigned_ranks_per_thread ) const -{ - size_t rank_end = rank_start + num_assigned_ranks_per_thread; - - // if we have more threads than ranks, or if ranks can not be - // distributed evenly on threads, we need to make sure, that all - // threads care only about existing ranks - if ( rank_end > kernel().mpi_manager.get_num_processes() ) - { - rank_end = std::max( rank_start, kernel().mpi_manager.get_num_processes() ); - } - - return rank_end; -} - -inline AssignedRanks -VPManager::get_assigned_ranks( const size_t tid ) -{ - AssignedRanks assigned_ranks; - assigned_ranks.begin = get_start_rank_per_thread( tid ); - assigned_ranks.max_size = get_num_assigned_ranks_per_thread(); - assigned_ranks.end = get_end_rank_per_thread( assigned_ranks.begin, assigned_ranks.max_size ); - assigned_ranks.size = assigned_ranks.end - assigned_ranks.begin; - return assigned_ranks; -} - -} // namespace nest - -#endif /* VP_MANAGER_IMPL_H */ From 4d545f5837bdd73ba312d872b5e70957f8e01dae Mon Sep 17 00:00:00 2001 From: Jan Vogelsang <47158055+JanVogelsang@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:18:19 +0200 Subject: [PATCH 02/15] Delete models/quantal_stp_synapse_impl.h --- models/quantal_stp_synapse_impl.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 models/quantal_stp_synapse_impl.h diff --git a/models/quantal_stp_synapse_impl.h b/models/quantal_stp_synapse_impl.h deleted file mode 100644 index e69de29bb2..0000000000 From 649a448a834fbeedf43463344856bb47dcce0aff Mon Sep 17 00:00:00 2001 From: Jan Vogelsang <47158055+JanVogelsang@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:44:35 +0200 Subject: [PATCH 03/15] Made previously non-inlinable functions inline --- models/glif_cond.cpp | 8 ------ models/glif_cond.h | 6 ++++ models/glif_psc_double_alpha.cpp | 8 ------ models/glif_psc_double_alpha.h | 6 ++++ models/iaf_bw_2001.cpp | 36 ----------------------- models/iaf_bw_2001.h | 35 +++++++++++++++++++++++ models/iaf_bw_2001_exact.cpp | 49 -------------------------------- models/iaf_bw_2001_exact.h | 48 +++++++++++++++++++++++++++++++ 8 files changed, 95 insertions(+), 101 deletions(-) diff --git a/models/glif_cond.cpp b/models/glif_cond.cpp index 3592cc281e..c6ad3f0895 100644 --- a/models/glif_cond.cpp +++ b/models/glif_cond.cpp @@ -800,12 +800,4 @@ nest::glif_cond::handle( CurrentEvent& e ) e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); } -// TODO JV -// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. -void -nest::glif_cond::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); // the logger does this for us -} - #endif // HAVE_GSL diff --git a/models/glif_cond.h b/models/glif_cond.h index acfbffef2b..3a2a7e1eaf 100644 --- a/models/glif_cond.h +++ b/models/glif_cond.h @@ -527,6 +527,12 @@ glif_cond::set_status( const DictionaryDatum& d ) S_ = stmp; } +inline void +nest::glif_cond::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); // the logger does this for us +} + } // namespace nest #endif // HAVE_GSL diff --git a/models/glif_psc_double_alpha.cpp b/models/glif_psc_double_alpha.cpp index c7168ae582..abf6ff3a6d 100644 --- a/models/glif_psc_double_alpha.cpp +++ b/models/glif_psc_double_alpha.cpp @@ -695,11 +695,3 @@ nest::glif_psc_double_alpha::handle( CurrentEvent& e ) B_.currents_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); } - -// TODO JV -// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. -void -nest::glif_psc_double_alpha::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); // the logger does this for us -} diff --git a/models/glif_psc_double_alpha.h b/models/glif_psc_double_alpha.h index 69a51a98b0..79934dd8a9 100644 --- a/models/glif_psc_double_alpha.h +++ b/models/glif_psc_double_alpha.h @@ -493,6 +493,12 @@ glif_psc_double_alpha::set_status( const DictionaryDatum& d ) S_ = stmp; } +inline void +glif_psc_double_alpha::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); // the logger does this for us +} + } // namespace nest #endif diff --git a/models/iaf_bw_2001.cpp b/models/iaf_bw_2001.cpp index 34c4ce0974..9c57db6753 100644 --- a/models/iaf_bw_2001.cpp +++ b/models/iaf_bw_2001.cpp @@ -484,41 +484,5 @@ nest::iaf_bw_2001::update( Time const& origin, const long from, const long to ) } } -// TODO JV -// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. -void -nest::iaf_bw_2001::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); -} - -void -nest::iaf_bw_2001::handle( SpikeEvent& e ) -{ - assert( e.get_delay_steps() > 0 ); - - const double steps = e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ); - - const auto rport = e.get_rport(); - - if ( rport < NMDA ) - { - B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() ); - } - else - { - B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() * e.get_offset() ); - } -} - -void -nest::iaf_bw_2001::handle( CurrentEvent& e ) -{ - assert( e.get_delay_steps() > 0 ); - - B_.currents_.add_value( - e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); -} - #endif // HAVE_BOOST #endif // HAVE_GSL diff --git a/models/iaf_bw_2001.h b/models/iaf_bw_2001.h index 3efbace816..450b044c07 100644 --- a/models/iaf_bw_2001.h +++ b/models/iaf_bw_2001.h @@ -523,6 +523,41 @@ iaf_bw_2001::set_status( const DictionaryDatum& d ) P_ = ptmp; S_ = stmp; }; + +inline void +iaf_bw_2001::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); +} + +inline void +iaf_bw_2001::handle( SpikeEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + const double steps = e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ); + + const auto rport = e.get_rport(); + + if ( rport < NMDA ) + { + B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() ); + } + else + { + B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() * e.get_offset() ); + } +} + +inline void +iaf_bw_2001::handle( CurrentEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + B_.currents_.add_value( + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); +} + } // namespace #endif // HAVE_BOOST diff --git a/models/iaf_bw_2001_exact.cpp b/models/iaf_bw_2001_exact.cpp index 537a21e325..64b67e96db 100644 --- a/models/iaf_bw_2001_exact.cpp +++ b/models/iaf_bw_2001_exact.cpp @@ -515,53 +515,4 @@ nest::iaf_bw_2001_exact::update( Time const& origin, const long from, const long } } -// TODO JV -// Do not move this function as inline to h-file. It depends on universal_data_logger.h being included here. -void -nest::iaf_bw_2001_exact::handle( DataLoggingRequest& e ) -{ - B_.logger_.handle( e ); -} - -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() ) ); - - const double steps = e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ); - const auto rport = e.get_rport(); - - if ( rport < NMDA ) - { - B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() ); - } - else - // we need to scale each individual S_j variable by its weight, - // so we store them - { - B_.spikes_[ rport - 1 ].add_value( steps, e.get_multiplicity() ); - // since we scale entire S_j variable by the weight it also affects previous spikes. - // we therefore require them to be constant. - const size_t w_idx = rport - NMDA; - if ( B_.weights_[ w_idx ] == 0 ) - { - B_.weights_[ w_idx ] = e.get_weight(); - } - else if ( B_.weights_[ w_idx ] != e.get_weight() ) - { - throw KernelException( "iaf_bw_2001_exact requires constant weights." ); - } - } -} - -void -nest::iaf_bw_2001_exact::handle( CurrentEvent& e ) -{ - assert( e.get_delay_steps() > 0 ); - - B_.currents_.add_value( - e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); -} - #endif // HAVE_GSL diff --git a/models/iaf_bw_2001_exact.h b/models/iaf_bw_2001_exact.h index cf650afefe..ff933e19a3 100644 --- a/models/iaf_bw_2001_exact.h +++ b/models/iaf_bw_2001_exact.h @@ -540,6 +540,54 @@ iaf_bw_2001_exact::set_status( const DictionaryDatum& d ) P_ = ptmp; S_ = stmp; }; + +inline void +nest::iaf_bw_2001_exact::handle( DataLoggingRequest& e ) +{ + B_.logger_.handle( e ); +} + +inline 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() ) ); + + const double steps = e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ); + const auto rport = e.get_rport(); + + if ( rport < NMDA ) + { + B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() ); + } + else + // we need to scale each individual S_j variable by its weight, + // so we store them + { + B_.spikes_[ rport - 1 ].add_value( steps, e.get_multiplicity() ); + // since we scale entire S_j variable by the weight it also affects previous spikes. + // we therefore require them to be constant. + const size_t w_idx = rport - NMDA; + if ( B_.weights_[ w_idx ] == 0 ) + { + B_.weights_[ w_idx ] = e.get_weight(); + } + else if ( B_.weights_[ w_idx ] != e.get_weight() ) + { + throw KernelException( "iaf_bw_2001_exact requires constant weights." ); + } + } +} + +inline void +nest::iaf_bw_2001_exact::handle( CurrentEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + B_.currents_.add_value( + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); +} + } // namespace #endif // HAVE_GSL From 390064ef4b07f53281e430e9bed4186ff561ab00 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Mon, 11 Aug 2025 14:51:35 +0200 Subject: [PATCH 04/15] Added static modifier --- nestkernel/connector_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nestkernel/connector_base.h b/nestkernel/connector_base.h index 55bf7398f3..32a00058e7 100644 --- a/nestkernel/connector_base.h +++ b/nestkernel/connector_base.h @@ -221,7 +221,7 @@ class ConnectorBase virtual void remove_disabled_connections( const size_t first_disabled_index ) = 0; protected: - void prepare_weight_recorder_event( WeightRecorderEvent& wr_e, + static void prepare_weight_recorder_event( WeightRecorderEvent& wr_e, const size_t tid, const synindex syn_id, const unsigned int lcid, From 1eded20645bec9680a7cc98e732403713969fdb6 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Mon, 11 Aug 2025 16:10:32 +0200 Subject: [PATCH 05/15] Simplified get_process_id_of_node_id implementation --- nestkernel/connection_manager.cpp | 4 ++-- nestkernel/mpi_manager.h | 22 ++++++++++++++++++++++ nestkernel/source_table.cpp | 6 +++--- nestkernel/vp_manager.h | 23 ----------------------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/nestkernel/connection_manager.cpp b/nestkernel/connection_manager.cpp index c6e4cf954e..aa08aac7bd 100644 --- a/nestkernel/connection_manager.cpp +++ b/nestkernel/connection_manager.cpp @@ -1531,7 +1531,7 @@ ConnectionManager::compute_compressed_secondary_recv_buffer_positions( const siz { const size_t source_node_id = source_table_.get_node_id( tid, syn_id, lcid ); const size_t sg_s_id = source_table_.pack_source_node_id_and_syn_id( source_node_id, syn_id ); - const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( source_node_id ); + const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( source_node_id ); positions[ lcid ] = buffer_pos_of_source_node_id_syn_id_[ sg_s_id ] + kernel().mpi_manager.get_recv_displacement_secondary_events_in_int( source_rank ); @@ -1836,7 +1836,7 @@ ConnectionManager::fill_target_buffer( const size_t tid, while ( source_2_idx != csd_maps.at( syn_id ).end() ) { const auto source_gid = source_2_idx->first; - const auto source_rank = kernel().vp_manager.get_process_id_of_node_id( source_gid ); + const auto source_rank = kernel().mpi_manager.get_process_id_of_node_id( source_gid ); if ( not( rank_start <= source_rank and source_rank < rank_end ) ) { // We are not responsible for this source. diff --git a/nestkernel/mpi_manager.h b/nestkernel/mpi_manager.h index f70bb09623..c64782d834 100644 --- a/nestkernel/mpi_manager.h +++ b/nestkernel/mpi_manager.h @@ -103,6 +103,11 @@ class MPIManager : public ManagerInterface */ size_t get_process_id_of_vp( const size_t vp ) const; + /* + * Return the process id of the node with the specified node ID. + */ + size_t get_process_id_of_node_id( const size_t node_id ) const; + /** * Finalize MPI communication (needs to be separate from MPIManager::finalize * when compiled with MUSIC since spikes can arrive and handlers called here) @@ -765,6 +770,23 @@ nest::MPIManager::get_process_id_of_vp( const size_t vp ) const #ifdef HAVE_MPI +inline size_t +MPIManager::get_process_id_of_node_id( const size_t node_id ) const +{ + return node_id % num_processes_; +} + +#else + +inline size_t +MPIManager::get_process_id_of_node_id( const size_t ) const +{ + return 0; +} + +#endif /* HAVE_MPI */ + +#ifdef HAVE_MPI // Variable to hold the MPI communicator to use. #ifdef HAVE_MUSIC extern MPI::Intracomm comm; diff --git a/nestkernel/source_table.cpp b/nestkernel/source_table.cpp index f82fca8312..e12349785e 100644 --- a/nestkernel/source_table.cpp +++ b/nestkernel/source_table.cpp @@ -242,7 +242,7 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t cit != ( *unique_secondary_source_node_id_syn_id ).end(); ++cit ) { - const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( cit->first ); + const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( cit->first ); const size_t event_size = kernel().model_manager.get_secondary_event_prototype( cit->second, tid ).size(); buffer_pos_of_source_node_id_syn_id.insert( @@ -277,7 +277,7 @@ nest::SourceTable::source_should_be_processed_( const size_t rank_start, const size_t rank_end, const Source& source ) const { - const size_t source_rank = kernel().vp_manager.get_process_id_of_node_id( source.get_node_id() ); + const size_t source_rank = kernel().mpi_manager.get_process_id_of_node_id( source.get_node_id() ); return not( source.is_processed() or source.is_disabled() @@ -409,7 +409,7 @@ nest::SourceTable::get_next_target_data( const size_t tid, // communicated via MPI, so we prepare to return the relevant data // set the source rank - source_rank = kernel().vp_manager.get_process_id_of_node_id( current_source.get_node_id() ); + source_rank = kernel().mpi_manager.get_process_id_of_node_id( current_source.get_node_id() ); if ( not populate_target_data_fields_( current_position, current_source, source_rank, next_target_data ) ) { diff --git a/nestkernel/vp_manager.h b/nestkernel/vp_manager.h index 597560f721..c4227d2596 100644 --- a/nestkernel/vp_manager.h +++ b/nestkernel/vp_manager.h @@ -89,11 +89,6 @@ class VPManager : public ManagerInterface */ size_t get_OMP_NUM_THREADS() const; - /* - * Return the process id of the node with the specified node ID. - */ - size_t get_process_id_of_node_id( const size_t node_id ) const; - /** * Returns true if the given global node exists on this vp. */ @@ -306,24 +301,6 @@ VPManager::get_assigned_ranks( const size_t tid ) return assigned_ranks; } -#ifdef HAVE_MPI - -inline size_t -nest::VPManager::get_process_id_of_node_id( const size_t node_id ) const -{ - return node_id % get_num_virtual_processes() % kernel().mpi_manager.get_num_processes(); -} - -#else // HAVE_MPI - -inline size_t -nest::VPManager::get_process_id_of_node_id( const size_t ) const -{ - return 0; -} - -#endif /* HAVE_MPI */ - } // namespace nest #endif /* #ifndef VP_MANAGER_H */ From 98c62758d18c305507295e46e62c9fe18e85ea5a Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Tue, 12 Aug 2025 18:30:47 +0200 Subject: [PATCH 06/15] Fixed remaining bugs --- models/glif_psc.cpp | 77 ++++++++++--------------------- models/glif_psc.h | 34 +++++++++++++- models/music_cont_in_proxy.cpp | 4 +- models/music_cont_out_proxy.cpp | 5 +- models/music_message_in_proxy.cpp | 5 +- models/music_rate_in_proxy.cpp | 4 +- models/music_rate_out_proxy.cpp | 8 ++-- nestkernel/connector_base_impl.h | 0 nestkernel/model_manager_impl.h | 0 nestkernel/nest_impl.h | 3 -- 10 files changed, 71 insertions(+), 69 deletions(-) delete mode 100644 nestkernel/connector_base_impl.h delete mode 100644 nestkernel/model_manager_impl.h diff --git a/models/glif_psc.cpp b/models/glif_psc.cpp index c0844856c3..4eb7e52ddc 100644 --- a/models/glif_psc.cpp +++ b/models/glif_psc.cpp @@ -38,10 +38,10 @@ using namespace nest; -nest::RecordablesMap< nest::glif_psc > nest::glif_psc::recordablesMap_; - namespace nest { +RecordablesMap< glif_psc > glif_psc::recordablesMap_; + void register_glif_psc( const std::string& name ) { @@ -52,23 +52,22 @@ register_glif_psc( const std::string& name ) // for each quantity to be recorded. template <> void -RecordablesMap< nest::glif_psc >::create() +RecordablesMap< glif_psc >::create() { - insert_( names::V_m, &nest::glif_psc::get_V_m_ ); - insert_( names::ASCurrents_sum, &nest::glif_psc::get_ASCurrents_sum_ ); - insert_( names::I, &nest::glif_psc::get_I_ ); - insert_( names::I_syn, &nest::glif_psc::get_I_syn_ ); - insert_( names::threshold, &nest::glif_psc::get_threshold_ ); - insert_( names::threshold_spike, &nest::glif_psc::get_threshold_spike_ ); - insert_( names::threshold_voltage, &nest::glif_psc::get_threshold_voltage_ ); -} + insert_( names::V_m, &glif_psc::get_V_m_ ); + insert_( names::ASCurrents_sum, &glif_psc::get_ASCurrents_sum_ ); + insert_( names::I, &glif_psc::get_I_ ); + insert_( names::I_syn, &glif_psc::get_I_syn_ ); + insert_( names::threshold, &glif_psc::get_threshold_ ); + insert_( names::threshold_spike, &glif_psc::get_threshold_spike_ ); + insert_( names::threshold_voltage, &glif_psc::get_threshold_voltage_ ); } /* ---------------------------------------------------------------- * Default constructors defining default parameters and state * ---------------------------------------------------------------- */ -nest::glif_psc::Parameters_::Parameters_() +glif_psc::Parameters_::Parameters_() : G_( 9.43 ) // in nS , E_L_( -78.85 ) // in mV , th_inf_( -51.68 - E_L_ ) // in mv, rel to E_L_, - 51.68 - E_L_, i.e., 27.17 @@ -93,7 +92,7 @@ nest::glif_psc::Parameters_::Parameters_() { } -nest::glif_psc::State_::State_( const Parameters_& p ) +glif_psc::State_::State_( const Parameters_& p ) : U_( 0.0 ) // in mV , threshold_( p.th_inf_ ) // in mV , threshold_spike_( 0.0 ) // in mV @@ -117,7 +116,7 @@ nest::glif_psc::State_::State_( const Parameters_& p ) * ---------------------------------------------------------------- */ void -nest::glif_psc::Parameters_::get( DictionaryDatum& d ) const +glif_psc::Parameters_::get( DictionaryDatum& d ) const { def< double >( d, names::V_th, th_inf_ + E_L_ ); def< double >( d, names::g, G_ ); @@ -147,7 +146,7 @@ nest::glif_psc::Parameters_::get( DictionaryDatum& d ) const } double -nest::glif_psc::Parameters_::set( const DictionaryDatum& d, Node* node ) +glif_psc::Parameters_::set( const DictionaryDatum& d, Node* node ) { // if E_L_ is changed, we need to adjust all variables defined relative to // E_L_ @@ -301,7 +300,7 @@ nest::glif_psc::Parameters_::set( const DictionaryDatum& d, Node* node ) } void -nest::glif_psc::State_::get( DictionaryDatum& d, const Parameters_& p ) const +glif_psc::State_::get( DictionaryDatum& d, const Parameters_& p ) const { def< double >( d, names::V_m, U_ + p.E_L_ ); def< std::vector< double > >( d, names::ASCurrents, ASCurrents_ ); @@ -310,7 +309,7 @@ nest::glif_psc::State_::get( DictionaryDatum& d, const Parameters_& p ) const } void -nest::glif_psc::State_::set( const DictionaryDatum& d, const Parameters_& p, double delta_EL, Node* node ) +glif_psc::State_::set( const DictionaryDatum& d, const Parameters_& p, double delta_EL, Node* node ) { if ( updateValueParam< double >( d, names::V_m, U_, node ) ) { @@ -349,12 +348,12 @@ nest::glif_psc::State_::set( const DictionaryDatum& d, const Parameters_& p, dou } } -nest::glif_psc::Buffers_::Buffers_( glif_psc& n ) +glif_psc::Buffers_::Buffers_( glif_psc& n ) : logger_( n ) { } -nest::glif_psc::Buffers_::Buffers_( const Buffers_&, glif_psc& n ) +glif_psc::Buffers_::Buffers_( const Buffers_&, glif_psc& n ) : logger_( n ) { } @@ -363,7 +362,7 @@ nest::glif_psc::Buffers_::Buffers_( const Buffers_&, glif_psc& n ) * Default and copy constructor for node * ---------------------------------------------------------------- */ -nest::glif_psc::glif_psc() +glif_psc::glif_psc() : ArchivingNode() , P_() , S_( P_ ) @@ -372,7 +371,7 @@ nest::glif_psc::glif_psc() recordablesMap_.create(); } -nest::glif_psc::glif_psc( const glif_psc& n ) +glif_psc::glif_psc( const glif_psc& n ) : ArchivingNode( n ) , P_( n.P_ ) , S_( n.S_ ) @@ -385,7 +384,7 @@ nest::glif_psc::glif_psc( const glif_psc& n ) * ---------------------------------------------------------------- */ void -nest::glif_psc::init_buffers_() +glif_psc::init_buffers_() { B_.spikes_.clear(); // includes resize B_.currents_.clear(); // include resize @@ -393,7 +392,7 @@ nest::glif_psc::init_buffers_() } void -nest::glif_psc::pre_run_hook() +glif_psc::pre_run_hook() { B_.logger_.init(); @@ -467,7 +466,7 @@ nest::glif_psc::pre_run_hook() * ---------------------------------------------------------------- */ void -nest::glif_psc::update( Time const& origin, const long from, const long to ) +glif_psc::update( Time const& origin, const long from, const long to ) { double v_old = S_.U_; @@ -596,32 +595,4 @@ nest::glif_psc::update( Time const& origin, const long from, const long to ) } } -size_t -nest::glif_psc::handles_test_event( SpikeEvent&, size_t receptor_type ) -{ - if ( receptor_type <= 0 or receptor_type > P_.n_receptors_() ) - { - throw IncompatibleReceptorType( receptor_type, get_name(), "SpikeEvent" ); - } - - P_.has_connections_ = true; - return receptor_type; -} - -void -nest::glif_psc::handle( SpikeEvent& e ) -{ - assert( e.get_delay_steps() > 0 ); - - B_.spikes_[ e.get_rport() - 1 ].add_value( - e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_multiplicity() ); -} - -void -nest::glif_psc::handle( CurrentEvent& e ) -{ - assert( e.get_delay_steps() > 0 ); - - B_.currents_.add_value( - e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); -} +} // namespace nest diff --git a/models/glif_psc.h b/models/glif_psc.h index d07e3a60aa..1215624ac7 100644 --- a/models/glif_psc.h +++ b/models/glif_psc.h @@ -461,12 +461,42 @@ glif_psc::set_status( const DictionaryDatum& d ) S_ = stmp; } -void -nest::glif_psc::handle( DataLoggingRequest& e ) +inline size_t +glif_psc::handles_test_event( SpikeEvent&, size_t receptor_type ) +{ + if ( receptor_type <= 0 or receptor_type > P_.n_receptors_() ) + { + throw IncompatibleReceptorType( receptor_type, get_name(), "SpikeEvent" ); + } + + P_.has_connections_ = true; + return receptor_type; +} + +inline void +glif_psc::handle( DataLoggingRequest& e ) { B_.logger_.handle( e ); // the logger does this for us } +inline void +glif_psc::handle( SpikeEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + B_.spikes_[ e.get_rport() - 1 ].add_value( + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_multiplicity() ); +} + +inline void +glif_psc::handle( CurrentEvent& e ) +{ + assert( e.get_delay_steps() > 0 ); + + B_.currents_.add_value( + e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() * e.get_current() ); +} + } // namespace nest #endif diff --git a/models/music_cont_in_proxy.cpp b/models/music_cont_in_proxy.cpp index 41dbb9269a..81494075a6 100644 --- a/models/music_cont_in_proxy.cpp +++ b/models/music_cont_in_proxy.cpp @@ -29,7 +29,6 @@ #include "dict.h" #include "dictutils.h" #include "doubledatum.h" -#include "integerdatum.h" // Includes from libnestutil: #include "compose.hpp" @@ -37,7 +36,10 @@ #include "logging.h" // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "music_manager.h" +#include "nest.h" void nest::register_music_cont_in_proxy( const std::string& name ) diff --git a/models/music_cont_out_proxy.cpp b/models/music_cont_out_proxy.cpp index 1eef0f015c..9398587e3b 100644 --- a/models/music_cont_out_proxy.cpp +++ b/models/music_cont_out_proxy.cpp @@ -29,7 +29,10 @@ #include // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "music_manager.h" +#include "nest.h" #include "nest_datums.h" // Includes from libnestutil: @@ -39,8 +42,6 @@ // Includes from sli: #include "dict.h" #include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" void nest::register_music_cont_out_proxy( const std::string& name ) diff --git a/models/music_message_in_proxy.cpp b/models/music_message_in_proxy.cpp index fd58c5947b..ff3eb4f955 100644 --- a/models/music_message_in_proxy.cpp +++ b/models/music_message_in_proxy.cpp @@ -29,15 +29,16 @@ // Includes from sli: #include "arraydatum.h" -#include "doubledatum.h" -#include "integerdatum.h" // Includes from libnestutil: #include "compose.hpp" #include "logging.h" // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "music_manager.h" +#include "nest.h" void nest::register_music_message_in_proxy( const std::string& name ) diff --git a/models/music_rate_in_proxy.cpp b/models/music_rate_in_proxy.cpp index 70028f3f9f..0aee2c2f2b 100644 --- a/models/music_rate_in_proxy.cpp +++ b/models/music_rate_in_proxy.cpp @@ -29,14 +29,16 @@ #include "dict.h" #include "dictutils.h" #include "doubledatum.h" -#include "integerdatum.h" // Includes from libnestutil: #include "compose.hpp" #include "logging.h" // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "music_manager.h" +#include "nest.h" void nest::register_music_rate_in_proxy( const std::string& name ) diff --git a/models/music_rate_out_proxy.cpp b/models/music_rate_out_proxy.cpp index e12631a0ef..df5f79f344 100644 --- a/models/music_rate_out_proxy.cpp +++ b/models/music_rate_out_proxy.cpp @@ -24,22 +24,20 @@ #ifdef HAVE_MUSIC -// C++ includes: -#include - // Includes from sli: #include "arraydatum.h" #include "dict.h" #include "dictutils.h" -#include "doubledatum.h" -#include "integerdatum.h" // Includes from libnestutil: #include "compose.hpp" #include "logging.h" // Includes from nestkernel: +#include "event_delivery_manager.h" #include "kernel_manager.h" +#include "music_manager.h" +#include "nest.h" /* ---------------------------------------------------------------- * Default constructors defining default parameters and state diff --git a/nestkernel/connector_base_impl.h b/nestkernel/connector_base_impl.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/nestkernel/model_manager_impl.h b/nestkernel/model_manager_impl.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/nestkernel/nest_impl.h b/nestkernel/nest_impl.h index 45da1a8808..1bfefd321b 100644 --- a/nestkernel/nest_impl.h +++ b/nestkernel/nest_impl.h @@ -22,10 +22,7 @@ // Includes from nestkernel: -#include "connector_model_impl.h" -#include "genericmodel_impl.h" #include "kernel_manager.h" -#include "model_manager_impl.h" namespace nest { From a63d91cb5ce970350734791aa65704bfd29be47b Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Tue, 12 Aug 2025 18:32:30 +0200 Subject: [PATCH 07/15] Removed nest_impl.h --- nestkernel/nest_impl.h | 43 ------------------------------------------ 1 file changed, 43 deletions(-) delete mode 100644 nestkernel/nest_impl.h diff --git a/nestkernel/nest_impl.h b/nestkernel/nest_impl.h deleted file mode 100644 index 1bfefd321b..0000000000 --- a/nestkernel/nest_impl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * nest_impl.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 . - * - */ - - -// Includes from nestkernel: -#include "kernel_manager.h" - -namespace nest -{ - -template < template < typename > class ConnectorModelT > -void -register_connection_model( const std::string& name ) -{ - kernel().model_manager.register_connection_model< ConnectorModelT >( name ); -} - -template < typename NodeModelT > -void -register_node_model( const std::string& name, std::string deprecation_info ) -{ - kernel().model_manager.register_node_model< NodeModelT >( name, deprecation_info ); -} -} From d85b30e55aa6627214f6340b20b4932dce2fedef Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 13:06:39 +0200 Subject: [PATCH 08/15] Minimized layer_impl.h --- nestkernel/layer.h | 490 ++++++++++++++++++++++++++++++++++++++++ nestkernel/layer_impl.h | 490 ---------------------------------------- 2 files changed, 490 insertions(+), 490 deletions(-) diff --git a/nestkernel/layer.h b/nestkernel/layer.h index 8e425e896d..054f79f35c 100644 --- a/nestkernel/layer.h +++ b/nestkernel/layer.h @@ -527,6 +527,496 @@ class MaskedLayer MaskDatum mask_; }; +inline void +AbstractLayer::set_node_collection( NodeCollectionPTR node_collection ) +{ + node_collection_ = node_collection; +} + + +inline NodeCollectionPTR +AbstractLayer::get_node_collection() +{ + return node_collection_; +} + +template < int D > +inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, + const MaskDatum& maskd, + bool allow_oversized, + NodeCollectionPTR node_collection ) + : mask_( maskd ) +{ + ntree_ = layer.get_global_positions_ntree( node_collection ); + + check_mask_( layer, allow_oversized ); +} + +template < int D > +inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, + const MaskDatum& maskd, + bool allow_oversized, + Layer< D >& target, + NodeCollectionPTR node_collection ) + : mask_( maskd ) +{ + ntree_ = layer.get_global_positions_ntree( + target.get_periodic_mask(), target.get_lower_left(), target.get_extent(), node_collection ); + + check_mask_( target, allow_oversized ); + mask_ = new ConverseMask< D >( dynamic_cast< const Mask< D >& >( *mask_ ) ); +} + +template < int D > +inline MaskedLayer< D >::~MaskedLayer() +{ +} + +template < int D > +inline typename Ntree< D, size_t >::masked_iterator +MaskedLayer< D >::begin( const Position< D >& anchor ) +{ + try + { + return ntree_->masked_begin( dynamic_cast< const Mask< D >& >( *mask_ ), anchor ); + } + catch ( std::bad_cast& e ) + { + throw BadProperty( "Mask is incompatible with layer." ); + } +} + +template < int D > +inline typename Ntree< D, size_t >::masked_iterator +MaskedLayer< D >::end() +{ + return ntree_->masked_end(); +} + +template < int D > +inline Layer< D >::Layer() +{ + // Default center (0,0) and extent (1,1) + for ( int i = 0; i < D; ++i ) + { + lower_left_[ i ] = -0.5; + extent_[ i ] = 1.0; + } +} + +template < int D > +inline Layer< D >::Layer( const Layer& other_layer ) + : AbstractLayer( other_layer ) + , lower_left_( other_layer.lower_left_ ) + , extent_( other_layer.extent_ ) + , periodic_( other_layer.periodic_ ) +{ +} + +template < int D > +inline Layer< D >::~Layer() +{ + if ( cached_ntree_md_ == get_metadata() ) + { + clear_ntree_cache_(); + } + + if ( cached_vector_md_ == get_metadata() ) + { + clear_vector_cache_(); + } +} + +template < int D > +inline Position< D > +Layer< D >::compute_displacement( const Position< D >& from_pos, const size_t to_lid ) const +{ + return compute_displacement( from_pos, get_position( to_lid ) ); +} + +template < int D > +inline std::vector< double > +Layer< D >::compute_displacement( const std::vector< double >& from_pos, const size_t to_lid ) const +{ + return std::vector< double >( compute_displacement( Position< D >( from_pos ), to_lid ).get_vector() ); +} + +template < int D > +inline double +Layer< D >::compute_distance( const Position< D >& from_pos, const size_t lid ) const +{ + return compute_displacement( from_pos, lid ).length(); +} + +template < int D > +inline double +Layer< D >::compute_distance( const std::vector< double >& from_pos, const size_t lid ) const +{ + return compute_displacement( Position< D >( from_pos ), lid ).length(); +} + +template < int D > +inline double +Layer< D >::compute_distance( const std::vector< double >& from_pos, const std::vector< double >& to_pos ) const +{ + double squared_displacement = 0; + for ( unsigned int i = 0; i < D; ++i ) + { + const double displacement = compute_displacement( from_pos, to_pos, i ); + squared_displacement += displacement * displacement; + } + return std::sqrt( squared_displacement ); +} + +template < int D > +inline std::vector< double > +Layer< D >::get_position_vector( const size_t sind ) const +{ + return get_position( sind ).get_vector(); +} + +template < int D > +inline void +Layer< D >::clear_ntree_cache_() const +{ + cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >(); + cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); +} + +template < int D > +inline void +Layer< D >::clear_vector_cache_() const +{ + if ( cached_vector_ != 0 ) + { + delete cached_vector_; + } + cached_vector_ = 0; + cached_vector_md_ = NodeCollectionMetadataPTR( nullptr ); +} + +template < int D > +std::shared_ptr< Ntree< D, size_t > > Layer< D >::cached_ntree_; + +template < int D > +std::vector< std::pair< Position< D >, size_t > >* Layer< D >::cached_vector_ = 0; + +template < int D > +Position< D > +Layer< D >::compute_displacement( const Position< D >& from_pos, const Position< D >& to_pos ) const +{ + Position< D > displ = to_pos; + for ( int i = 0; i < D; ++i ) + { + displ[ i ] -= from_pos[ i ]; + if ( periodic_[ i ] ) + { + displ[ i ] = -0.5 * extent_[ i ] + std::fmod( displ[ i ] + 0.5 * extent_[ i ], extent_[ i ] ); + if ( displ[ i ] < -0.5 * extent_[ i ] ) + { + displ[ i ] += extent_[ i ]; + } + } + } + return displ; +} + +template < int D > +double +Layer< D >::compute_displacement( const std::vector< double >& from_pos, + const std::vector< double >& to_pos, + const unsigned int dimension ) const +{ + double displacement = to_pos[ dimension ] - from_pos[ dimension ]; + if ( periodic_[ dimension ] ) + { + displacement -= extent_[ dimension ] * std::round( displacement * ( 1 / extent_[ dimension ] ) ); + } + return displacement; +} + +template < int D > +void +Layer< D >::set_status( const DictionaryDatum& d ) +{ + if ( d->known( names::edge_wrap ) ) + { + if ( getValue< bool >( d, names::edge_wrap ) ) + { + periodic_ = ( 1 << D ) - 1; // All dimensions periodic + } + } +} + +template < int D > +void +Layer< D >::get_status( DictionaryDatum& d, NodeCollection const* nc ) const +{ + ( *d )[ names::extent ] = std::vector< double >( extent_.get_vector() ); + ( *d )[ names::center ] = std::vector< double >( ( lower_left_ + extent_ / 2 ).get_vector() ); + + if ( periodic_.none() ) + { + ( *d )[ names::edge_wrap ] = BoolDatum( false ); + } + else if ( periodic_.count() == D ) + { + ( *d )[ names::edge_wrap ] = true; + } + + if ( nc ) + { + // This is for backward compatibility with some tests and scripts + // TODO: Rename parameter + ( *d )[ names::network_size ] = nc->size(); + } +} + +template < int D > +void +Layer< D >::connect( NodeCollectionPTR source_nc, + AbstractLayerPTR target_layer, + NodeCollectionPTR target_nc, + ConnectionCreator& connector ) +{ + // We need to extract the real pointer here to be able to cast to the + // dimension-specific subclass. + AbstractLayer* target_abs = target_layer.get(); + assert( target_abs ); + + try + { + Layer< D >& tgt = dynamic_cast< Layer< D >& >( *target_abs ); + connector.connect( *this, source_nc, tgt, target_nc ); + } + catch ( std::bad_cast& e ) + { + throw BadProperty( "Target layer must have same number of dimensions as source layer." ); + } +} + +template < int D > +std::shared_ptr< Ntree< D, size_t > > +Layer< D >::get_global_positions_ntree( NodeCollectionPTR node_collection ) +{ + if ( cached_ntree_md_ == node_collection->get_metadata() ) + { + assert( cached_ntree_.get() ); + return cached_ntree_; + } + + clear_ntree_cache_(); + + cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >( + new Ntree< D, size_t >( this->lower_left_, this->extent_, this->periodic_ ) ); + + return do_get_global_positions_ntree_( node_collection ); +} + +template < int D > +std::shared_ptr< Ntree< D, size_t > > +Layer< D >::get_global_positions_ntree( std::bitset< D > periodic, + Position< D > lower_left, + Position< D > extent, + NodeCollectionPTR node_collection ) +{ + clear_ntree_cache_(); + clear_vector_cache_(); + + // Keep layer geometry for non-periodic dimensions + for ( int i = 0; i < D; ++i ) + { + if ( not periodic[ i ] ) + { + extent[ i ] = extent_[ i ]; + lower_left[ i ] = lower_left_[ i ]; + } + } + + cached_ntree_ = + std::shared_ptr< Ntree< D, size_t > >( new Ntree< D, size_t >( this->lower_left_, extent, periodic ) ); + + do_get_global_positions_ntree_( node_collection ); + + // Do not use cache since the periodic bits and extents were altered. + cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); + + return cached_ntree_; +} + +template < int D > +std::shared_ptr< Ntree< D, size_t > > +Layer< D >::do_get_global_positions_ntree_( NodeCollectionPTR node_collection ) +{ + if ( cached_vector_md_ == node_collection->get_metadata() ) + { + // Convert from vector to Ntree + + typename std::insert_iterator< Ntree< D, size_t > > to = std::inserter( *cached_ntree_, cached_ntree_->end() ); + + for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator from = cached_vector_->begin(); + from != cached_vector_->end(); + ++from ) + { + *to = *from; + } + } + else + { + + insert_global_positions_ntree_( *cached_ntree_, node_collection ); + } + + clear_vector_cache_(); + + cached_ntree_md_ = node_collection->get_metadata(); + + return cached_ntree_; +} + +template < int D > +std::vector< std::pair< Position< D >, size_t > >* +Layer< D >::get_global_positions_vector( NodeCollectionPTR node_collection ) +{ + if ( cached_vector_md_ == node_collection->get_metadata() ) + { + assert( cached_vector_ ); + return cached_vector_; + } + + clear_vector_cache_(); + + cached_vector_ = new std::vector< std::pair< Position< D >, size_t > >; + + if ( cached_ntree_md_ == node_collection->get_metadata() ) + { + // Convert from NTree to vector + + typename std::back_insert_iterator< std::vector< std::pair< Position< D >, size_t > > > to = + std::back_inserter( *cached_vector_ ); + + for ( typename Ntree< D, size_t >::iterator from = cached_ntree_->begin(); from != cached_ntree_->end(); ++from ) + { + *to = *from; + } + } + else + { + insert_global_positions_vector_( *cached_vector_, node_collection ); + } + + clear_ntree_cache_(); + + cached_vector_md_ = node_collection->get_metadata(); + + return cached_vector_; +} + +template < int D > +std::vector< std::pair< Position< D >, size_t > > +Layer< D >::get_global_positions_vector( const MaskDatum& mask, + const Position< D >& anchor, + bool allow_oversized, + NodeCollectionPTR node_collection ) +{ + MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection ); + std::vector< std::pair< Position< D >, size_t > > positions; + + for ( typename Ntree< D, size_t >::masked_iterator iter = masked_layer.begin( anchor ); iter != masked_layer.end(); + ++iter ) + { + positions.push_back( *iter ); + } + + return positions; +} + +template < int D > +std::vector< size_t > +Layer< D >::get_global_nodes( const MaskDatum& mask, + const std::vector< double >& anchor, + bool allow_oversized, + NodeCollectionPTR node_collection ) +{ + MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection ); + std::vector< size_t > nodes; + for ( typename Ntree< D, size_t >::masked_iterator i = masked_layer.begin( anchor ); i != masked_layer.end(); ++i ) + { + nodes.push_back( i->second ); + } + return nodes; +} + +template < int D > +void +Layer< D >::dump_nodes( std::ostream& out ) const +{ + for ( NodeCollection::const_iterator it = this->node_collection_->rank_local_begin(); + it < this->node_collection_->end(); + ++it ) + { + out << ( *it ).node_id << ' '; + get_position( ( *it ).nc_index ).print( out ); + out << std::endl; + } +} + +template < int D > +void +Layer< D >::dump_connections( std::ostream& out, + NodeCollectionPTR node_collection, + AbstractLayerPTR target_layer, + const Token& syn_model ) +{ + // Find all connections for given sources, targets and synapse model + DictionaryDatum conn_filter( new Dictionary ); + def( conn_filter, names::source, NodeCollectionDatum( node_collection ) ); + def( conn_filter, names::target, NodeCollectionDatum( target_layer->get_node_collection() ) ); + def( conn_filter, names::synapse_model, syn_model ); + ArrayDatum connectome = kernel::manager< ConnectionManager >().get_connections( conn_filter ); + + // Get positions of remote nodes + std::vector< std::pair< Position< D >, size_t > >* src_vec = get_global_positions_vector( node_collection ); + + // Iterate over connectome and write every connection, looking up source position only if source neuron changes + size_t previous_source_node_id = 0; // dummy initial value, cannot be node_id of any node + Position< D > source_pos; // dummy value + for ( const auto& entry : connectome ) + { + ConnectionDatum conn = getValue< ConnectionDatum >( entry ); + const size_t source_node_id = conn.get_source_node_id(); + + // Search source_pos for source node only if it is a different node + if ( source_node_id != previous_source_node_id ) + { + const auto it = std::find_if( src_vec->begin(), + src_vec->end(), + [ source_node_id ]( const std::pair< Position< D >, size_t >& p ) { return p.second == source_node_id; } ); + assert( it != src_vec->end() ); // internal error if node not found + + source_pos = it->first; + previous_source_node_id = source_node_id; + } + + DictionaryDatum result_dict = kernel::manager< ConnectionManager >().get_synapse_status( source_node_id, + conn.get_target_node_id(), + conn.get_target_thread(), + conn.get_synapse_model_id(), + conn.get_port() ); + const long target_node_id = getValue< long >( result_dict, names::target ); + const double weight = getValue< double >( result_dict, names::weight ); + const double delay = getValue< double >( result_dict, names::delay ); + const Layer< D >* const tgt_layer = dynamic_cast< Layer< D >* >( target_layer.get() ); + const long tnode_lid = tgt_layer->node_collection_->get_nc_index( target_node_id ); + assert( tnode_lid >= 0 ); + + // Print source, target, weight, delay, rports + out << source_node_id << ' ' << target_node_id << ' ' << weight << ' ' << delay << ' '; + tgt_layer->compute_displacement( source_pos, tnode_lid ).print( out ); + out << '\n'; + } +} + } // namespace nest #endif diff --git a/nestkernel/layer_impl.h b/nestkernel/layer_impl.h index 7f96d0e44b..f181e1ec6d 100644 --- a/nestkernel/layer_impl.h +++ b/nestkernel/layer_impl.h @@ -25,496 +25,6 @@ namespace nest { -inline void -AbstractLayer::set_node_collection( NodeCollectionPTR node_collection ) -{ - node_collection_ = node_collection; -} - - -inline NodeCollectionPTR -AbstractLayer::get_node_collection() -{ - return node_collection_; -} - -template < int D > -inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, - const MaskDatum& maskd, - bool allow_oversized, - NodeCollectionPTR node_collection ) - : mask_( maskd ) -{ - ntree_ = layer.get_global_positions_ntree( node_collection ); - - check_mask_( layer, allow_oversized ); -} - -template < int D > -inline MaskedLayer< D >::MaskedLayer( Layer< D >& layer, - const MaskDatum& maskd, - bool allow_oversized, - Layer< D >& target, - NodeCollectionPTR node_collection ) - : mask_( maskd ) -{ - ntree_ = layer.get_global_positions_ntree( - target.get_periodic_mask(), target.get_lower_left(), target.get_extent(), node_collection ); - - check_mask_( target, allow_oversized ); - mask_ = new ConverseMask< D >( dynamic_cast< const Mask< D >& >( *mask_ ) ); -} - -template < int D > -inline MaskedLayer< D >::~MaskedLayer() -{ -} - -template < int D > -inline typename Ntree< D, size_t >::masked_iterator -MaskedLayer< D >::begin( const Position< D >& anchor ) -{ - try - { - return ntree_->masked_begin( dynamic_cast< const Mask< D >& >( *mask_ ), anchor ); - } - catch ( std::bad_cast& e ) - { - throw BadProperty( "Mask is incompatible with layer." ); - } -} - -template < int D > -inline typename Ntree< D, size_t >::masked_iterator -MaskedLayer< D >::end() -{ - return ntree_->masked_end(); -} - -template < int D > -inline Layer< D >::Layer() -{ - // Default center (0,0) and extent (1,1) - for ( int i = 0; i < D; ++i ) - { - lower_left_[ i ] = -0.5; - extent_[ i ] = 1.0; - } -} - -template < int D > -inline Layer< D >::Layer( const Layer& other_layer ) - : AbstractLayer( other_layer ) - , lower_left_( other_layer.lower_left_ ) - , extent_( other_layer.extent_ ) - , periodic_( other_layer.periodic_ ) -{ -} - -template < int D > -inline Layer< D >::~Layer() -{ - if ( cached_ntree_md_ == get_metadata() ) - { - clear_ntree_cache_(); - } - - if ( cached_vector_md_ == get_metadata() ) - { - clear_vector_cache_(); - } -} - -template < int D > -inline Position< D > -Layer< D >::compute_displacement( const Position< D >& from_pos, const size_t to_lid ) const -{ - return compute_displacement( from_pos, get_position( to_lid ) ); -} - -template < int D > -inline std::vector< double > -Layer< D >::compute_displacement( const std::vector< double >& from_pos, const size_t to_lid ) const -{ - return std::vector< double >( compute_displacement( Position< D >( from_pos ), to_lid ).get_vector() ); -} - -template < int D > -inline double -Layer< D >::compute_distance( const Position< D >& from_pos, const size_t lid ) const -{ - return compute_displacement( from_pos, lid ).length(); -} - -template < int D > -inline double -Layer< D >::compute_distance( const std::vector< double >& from_pos, const size_t lid ) const -{ - return compute_displacement( Position< D >( from_pos ), lid ).length(); -} - -template < int D > -inline double -Layer< D >::compute_distance( const std::vector< double >& from_pos, const std::vector< double >& to_pos ) const -{ - double squared_displacement = 0; - for ( unsigned int i = 0; i < D; ++i ) - { - const double displacement = compute_displacement( from_pos, to_pos, i ); - squared_displacement += displacement * displacement; - } - return std::sqrt( squared_displacement ); -} - -template < int D > -inline std::vector< double > -Layer< D >::get_position_vector( const size_t sind ) const -{ - return get_position( sind ).get_vector(); -} - -template < int D > -inline void -Layer< D >::clear_ntree_cache_() const -{ - cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >(); - cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); -} - -template < int D > -inline void -Layer< D >::clear_vector_cache_() const -{ - if ( cached_vector_ != 0 ) - { - delete cached_vector_; - } - cached_vector_ = 0; - cached_vector_md_ = NodeCollectionMetadataPTR( nullptr ); -} - -template < int D > -std::shared_ptr< Ntree< D, size_t > > Layer< D >::cached_ntree_; - -template < int D > -std::vector< std::pair< Position< D >, size_t > >* Layer< D >::cached_vector_ = 0; - -template < int D > -Position< D > -Layer< D >::compute_displacement( const Position< D >& from_pos, const Position< D >& to_pos ) const -{ - Position< D > displ = to_pos; - for ( int i = 0; i < D; ++i ) - { - displ[ i ] -= from_pos[ i ]; - if ( periodic_[ i ] ) - { - displ[ i ] = -0.5 * extent_[ i ] + std::fmod( displ[ i ] + 0.5 * extent_[ i ], extent_[ i ] ); - if ( displ[ i ] < -0.5 * extent_[ i ] ) - { - displ[ i ] += extent_[ i ]; - } - } - } - return displ; -} - -template < int D > -double -Layer< D >::compute_displacement( const std::vector< double >& from_pos, - const std::vector< double >& to_pos, - const unsigned int dimension ) const -{ - double displacement = to_pos[ dimension ] - from_pos[ dimension ]; - if ( periodic_[ dimension ] ) - { - displacement -= extent_[ dimension ] * std::round( displacement * ( 1 / extent_[ dimension ] ) ); - } - return displacement; -} - -template < int D > -void -Layer< D >::set_status( const DictionaryDatum& d ) -{ - if ( d->known( names::edge_wrap ) ) - { - if ( getValue< bool >( d, names::edge_wrap ) ) - { - periodic_ = ( 1 << D ) - 1; // All dimensions periodic - } - } -} - -template < int D > -void -Layer< D >::get_status( DictionaryDatum& d, NodeCollection const* nc ) const -{ - ( *d )[ names::extent ] = std::vector< double >( extent_.get_vector() ); - ( *d )[ names::center ] = std::vector< double >( ( lower_left_ + extent_ / 2 ).get_vector() ); - - if ( periodic_.none() ) - { - ( *d )[ names::edge_wrap ] = BoolDatum( false ); - } - else if ( periodic_.count() == D ) - { - ( *d )[ names::edge_wrap ] = true; - } - - if ( nc ) - { - // This is for backward compatibility with some tests and scripts - // TODO: Rename parameter - ( *d )[ names::network_size ] = nc->size(); - } -} - -template < int D > -void -Layer< D >::connect( NodeCollectionPTR source_nc, - AbstractLayerPTR target_layer, - NodeCollectionPTR target_nc, - ConnectionCreator& connector ) -{ - // We need to extract the real pointer here to be able to cast to the - // dimension-specific subclass. - AbstractLayer* target_abs = target_layer.get(); - assert( target_abs ); - - try - { - Layer< D >& tgt = dynamic_cast< Layer< D >& >( *target_abs ); - connector.connect( *this, source_nc, tgt, target_nc ); - } - catch ( std::bad_cast& e ) - { - throw BadProperty( "Target layer must have same number of dimensions as source layer." ); - } -} - -template < int D > -std::shared_ptr< Ntree< D, size_t > > -Layer< D >::get_global_positions_ntree( NodeCollectionPTR node_collection ) -{ - if ( cached_ntree_md_ == node_collection->get_metadata() ) - { - assert( cached_ntree_.get() ); - return cached_ntree_; - } - - clear_ntree_cache_(); - - cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >( - new Ntree< D, size_t >( this->lower_left_, this->extent_, this->periodic_ ) ); - - return do_get_global_positions_ntree_( node_collection ); -} - -template < int D > -std::shared_ptr< Ntree< D, size_t > > -Layer< D >::get_global_positions_ntree( std::bitset< D > periodic, - Position< D > lower_left, - Position< D > extent, - NodeCollectionPTR node_collection ) -{ - clear_ntree_cache_(); - clear_vector_cache_(); - - // Keep layer geometry for non-periodic dimensions - for ( int i = 0; i < D; ++i ) - { - if ( not periodic[ i ] ) - { - extent[ i ] = extent_[ i ]; - lower_left[ i ] = lower_left_[ i ]; - } - } - - cached_ntree_ = - std::shared_ptr< Ntree< D, size_t > >( new Ntree< D, size_t >( this->lower_left_, extent, periodic ) ); - - do_get_global_positions_ntree_( node_collection ); - - // Do not use cache since the periodic bits and extents were altered. - cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr ); - - return cached_ntree_; -} - -template < int D > -std::shared_ptr< Ntree< D, size_t > > -Layer< D >::do_get_global_positions_ntree_( NodeCollectionPTR node_collection ) -{ - if ( cached_vector_md_ == node_collection->get_metadata() ) - { - // Convert from vector to Ntree - - typename std::insert_iterator< Ntree< D, size_t > > to = std::inserter( *cached_ntree_, cached_ntree_->end() ); - - for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator from = cached_vector_->begin(); - from != cached_vector_->end(); - ++from ) - { - *to = *from; - } - } - else - { - - insert_global_positions_ntree_( *cached_ntree_, node_collection ); - } - - clear_vector_cache_(); - - cached_ntree_md_ = node_collection->get_metadata(); - - return cached_ntree_; -} - -template < int D > -std::vector< std::pair< Position< D >, size_t > >* -Layer< D >::get_global_positions_vector( NodeCollectionPTR node_collection ) -{ - if ( cached_vector_md_ == node_collection->get_metadata() ) - { - assert( cached_vector_ ); - return cached_vector_; - } - - clear_vector_cache_(); - - cached_vector_ = new std::vector< std::pair< Position< D >, size_t > >; - - if ( cached_ntree_md_ == node_collection->get_metadata() ) - { - // Convert from NTree to vector - - typename std::back_insert_iterator< std::vector< std::pair< Position< D >, size_t > > > to = - std::back_inserter( *cached_vector_ ); - - for ( typename Ntree< D, size_t >::iterator from = cached_ntree_->begin(); from != cached_ntree_->end(); ++from ) - { - *to = *from; - } - } - else - { - insert_global_positions_vector_( *cached_vector_, node_collection ); - } - - clear_ntree_cache_(); - - cached_vector_md_ = node_collection->get_metadata(); - - return cached_vector_; -} - -template < int D > -std::vector< std::pair< Position< D >, size_t > > -Layer< D >::get_global_positions_vector( const MaskDatum& mask, - const Position< D >& anchor, - bool allow_oversized, - NodeCollectionPTR node_collection ) -{ - MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection ); - std::vector< std::pair< Position< D >, size_t > > positions; - - for ( typename Ntree< D, size_t >::masked_iterator iter = masked_layer.begin( anchor ); iter != masked_layer.end(); - ++iter ) - { - positions.push_back( *iter ); - } - - return positions; -} - -template < int D > -std::vector< size_t > -Layer< D >::get_global_nodes( const MaskDatum& mask, - const std::vector< double >& anchor, - bool allow_oversized, - NodeCollectionPTR node_collection ) -{ - MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection ); - std::vector< size_t > nodes; - for ( typename Ntree< D, size_t >::masked_iterator i = masked_layer.begin( anchor ); i != masked_layer.end(); ++i ) - { - nodes.push_back( i->second ); - } - return nodes; -} - -template < int D > -void -Layer< D >::dump_nodes( std::ostream& out ) const -{ - for ( NodeCollection::const_iterator it = this->node_collection_->rank_local_begin(); - it < this->node_collection_->end(); - ++it ) - { - out << ( *it ).node_id << ' '; - get_position( ( *it ).nc_index ).print( out ); - out << std::endl; - } -} - -template < int D > -void -Layer< D >::dump_connections( std::ostream& out, - NodeCollectionPTR node_collection, - AbstractLayerPTR target_layer, - const Token& syn_model ) -{ - // Find all connections for given sources, targets and synapse model - DictionaryDatum conn_filter( new Dictionary ); - def( conn_filter, names::source, NodeCollectionDatum( node_collection ) ); - def( conn_filter, names::target, NodeCollectionDatum( target_layer->get_node_collection() ) ); - def( conn_filter, names::synapse_model, syn_model ); - ArrayDatum connectome = kernel().connection_manager.get_connections( conn_filter ); - - // Get positions of remote nodes - std::vector< std::pair< Position< D >, size_t > >* src_vec = get_global_positions_vector( node_collection ); - - // Iterate over connectome and write every connection, looking up source position only if source neuron changes - size_t previous_source_node_id = 0; // dummy initial value, cannot be node_id of any node - Position< D > source_pos; // dummy value - for ( const auto& entry : connectome ) - { - ConnectionDatum conn = getValue< ConnectionDatum >( entry ); - const size_t source_node_id = conn.get_source_node_id(); - - // Search source_pos for source node only if it is a different node - if ( source_node_id != previous_source_node_id ) - { - const auto it = std::find_if( src_vec->begin(), - src_vec->end(), - [ source_node_id ]( const std::pair< Position< D >, size_t >& p ) { return p.second == source_node_id; } ); - assert( it != src_vec->end() ); // internal error if node not found - - source_pos = it->first; - previous_source_node_id = source_node_id; - } - - DictionaryDatum result_dict = kernel().connection_manager.get_synapse_status( source_node_id, - conn.get_target_node_id(), - conn.get_target_thread(), - conn.get_synapse_model_id(), - conn.get_port() ); - const long target_node_id = getValue< long >( result_dict, names::target ); - const double weight = getValue< double >( result_dict, names::weight ); - const double delay = getValue< double >( result_dict, names::delay ); - const Layer< D >* const tgt_layer = dynamic_cast< Layer< D >* >( target_layer.get() ); - const long tnode_lid = tgt_layer->node_collection_->get_nc_index( target_node_id ); - assert( tnode_lid >= 0 ); - - // Print source, target, weight, delay, rports - out << source_node_id << ' ' << target_node_id << ' ' << weight << ' ' << delay << ' '; - tgt_layer->compute_displacement( source_pos, tnode_lid ).print( out ); - out << '\n'; - } -} - template < int D > void MaskedLayer< D >::check_mask_( Layer< D >& layer, bool allow_oversized ) From cd6271f9d6667daf8032071a4af3079386fa8902 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang <47158055+JanVogelsang@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:11:11 +0200 Subject: [PATCH 09/15] Update models/CMakeLists.txt Co-authored-by: Dennis Terhorst --- models/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt index 3746c98cf0..5da8995e4e 100644 --- a/models/CMakeLists.txt +++ b/models/CMakeLists.txt @@ -24,9 +24,9 @@ set(models_sources cm_compartmentcurrents.h cm_compartmentcurrents.cpp cm_tree.h cm_tree.cpp rate_neuron_ipn.h - rate_neuron_opn.h - rate_transformer_node.h - weight_optimizer.h weight_optimizer.cpp + rate_neuron_opn.h + rate_transformer_node.h + weight_optimizer.h weight_optimizer.cpp ${MODELS_SOURCES_GENERATED} ) From 6ebf55fe08ed74df855b7868fdbfd5c78f796ef5 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 13:25:30 +0200 Subject: [PATCH 10/15] Fixed cherry-pick issue --- nestkernel/layer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nestkernel/layer.h b/nestkernel/layer.h index 054f79f35c..2f14812ff5 100644 --- a/nestkernel/layer.h +++ b/nestkernel/layer.h @@ -973,7 +973,7 @@ Layer< D >::dump_connections( std::ostream& out, def( conn_filter, names::source, NodeCollectionDatum( node_collection ) ); def( conn_filter, names::target, NodeCollectionDatum( target_layer->get_node_collection() ) ); def( conn_filter, names::synapse_model, syn_model ); - ArrayDatum connectome = kernel::manager< ConnectionManager >().get_connections( conn_filter ); + ArrayDatum connectome = kernel().connection_manager.get_connections( conn_filter ); // Get positions of remote nodes std::vector< std::pair< Position< D >, size_t > >* src_vec = get_global_positions_vector( node_collection ); @@ -998,7 +998,7 @@ Layer< D >::dump_connections( std::ostream& out, previous_source_node_id = source_node_id; } - DictionaryDatum result_dict = kernel::manager< ConnectionManager >().get_synapse_status( source_node_id, + DictionaryDatum result_dict = kernel().connection_manager.get_synapse_status( source_node_id, conn.get_target_node_id(), conn.get_target_thread(), conn.get_synapse_model_id(), From 9884718aa5414989724d3bc9d7941e69daaae1a4 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 13:25:46 +0200 Subject: [PATCH 11/15] Fixed non-MPI version --- nestkernel/io_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nestkernel/io_manager.cpp b/nestkernel/io_manager.cpp index 4633285782..5a1f9dd75d 100644 --- a/nestkernel/io_manager.cpp +++ b/nestkernel/io_manager.cpp @@ -47,6 +47,8 @@ #ifdef HAVE_MPI #include "recording_backend_mpi.h" #include "stimulation_backend_mpi.h" +#else +#include "stimulation_backend.h" #endif #ifdef HAVE_SIONLIB #include "recording_backend_sionlib.h" From 076e11a7ef1fb418824f8d99aee7c8cb71d73ffa Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 13:52:03 +0200 Subject: [PATCH 12/15] Fixed conngen --- nestkernel/conn_builder_conngen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nestkernel/conn_builder_conngen.cpp b/nestkernel/conn_builder_conngen.cpp index 7c0547ab34..f6699cc501 100644 --- a/nestkernel/conn_builder_conngen.cpp +++ b/nestkernel/conn_builder_conngen.cpp @@ -26,6 +26,8 @@ // Includes from nestkernel: #include "kernel_manager.h" +#include "nest.h" +#include "node_manager.h" // Includes from sli: #include "dictutils.h" From 0313d499cae5645caa035d43473fabe38c154ca8 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 14:37:16 +0200 Subject: [PATCH 13/15] Fixed sonata --- nestkernel/sonata_connector.cpp | 2 ++ nestkernel/sonata_connector.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nestkernel/sonata_connector.cpp b/nestkernel/sonata_connector.cpp index 59b7583c66..3a1d205623 100644 --- a/nestkernel/sonata_connector.cpp +++ b/nestkernel/sonata_connector.cpp @@ -30,6 +30,8 @@ // Includes from nestkernel: #include "kernel_manager.h" +#include "nest.h" +#include "node_manager.h" // Includes from sli: #include "dictutils.h" diff --git a/nestkernel/sonata_connector.h b/nestkernel/sonata_connector.h index 4420346b0e..2f2e0395b0 100644 --- a/nestkernel/sonata_connector.h +++ b/nestkernel/sonata_connector.h @@ -29,11 +29,11 @@ // C++ includes: #include +#include #include // Includes from nestkernel: #include "conn_parameter.h" -#include "kernel_manager.h" #include "nest_datums.h" #include "H5Cpp.h" From 508e349aa4e6bce3c7fc3f58653941689197f5af Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 15:13:06 +0200 Subject: [PATCH 14/15] Fixed sionlib --- nestkernel/recording_backend_sionlib.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nestkernel/recording_backend_sionlib.cpp b/nestkernel/recording_backend_sionlib.cpp index 33753117e5..d24706eee9 100644 --- a/nestkernel/recording_backend_sionlib.cpp +++ b/nestkernel/recording_backend_sionlib.cpp @@ -32,12 +32,13 @@ // Includes from libnestutil: #include "compose.hpp" -// Includes from nest: -#include "../nest/neststartup.h" - // Includes from nestkernel: +#include "io_manager.h" +#include "logging.h" +#include "logging_manager.h" #include "recording_backend_sionlib.h" #include "recording_device.h" +#include "simulation_manager.h" const unsigned int nest::RecordingBackendSIONlib::SIONLIB_REC_BACKEND_VERSION = 2; const unsigned int nest::RecordingBackendSIONlib::DEV_NAME_BUFFERSIZE = 32; From ba7cfc68d79c4383da6015ff6b25441aa886b4a0 Mon Sep 17 00:00:00 2001 From: Jan Vogelsang Date: Wed, 13 Aug 2025 15:49:13 +0200 Subject: [PATCH 15/15] Attempting to fix macos issue --- nestkernel/recording_backend_mpi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nestkernel/recording_backend_mpi.cpp b/nestkernel/recording_backend_mpi.cpp index 127adb1647..2056bf7857 100644 --- a/nestkernel/recording_backend_mpi.cpp +++ b/nestkernel/recording_backend_mpi.cpp @@ -22,7 +22,7 @@ // C++ includes: #include - +#include // Includes from nestkernel: #include "exceptions.h"