diff --git a/CMakeLists.txt b/CMakeLists.txt
index 07633c092c..a35a169e51 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,7 +113,6 @@ include( CheckIncludesSymbols )
# These includes publish function names.
include( ProcessOptions )
-include( WriteStaticModules_h )
include( CheckExtraCompilerFeatures )
include( ConfigureSummary )
include( GetTriple )
@@ -170,8 +169,6 @@ nest_get_color_flags()
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEST_C_COLOR_FLAGS}" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${NEST_CXX_COLOR_FLAGS}" )
-nest_write_static_module_header( "${PROJECT_BINARY_DIR}/nest/static_modules.h" )
-
# check additionals
nest_check_exitcode_abort()
nest_check_exitcode_segfault()
diff --git a/build_support/check_copyright_headers.py b/build_support/check_copyright_headers.py
index b54eaec464..b7c2147963 100644
--- a/build_support/check_copyright_headers.py
+++ b/build_support/check_copyright_headers.py
@@ -81,7 +81,6 @@ def eprint(*args, **kwargs):
exclude_files = [
"doc/copyright_header.cpp",
"doc/copyright_header.py",
- "nest/static_modules.h",
"pynest/pynestkernel.cpp",
"get-pip.py",
]
diff --git a/build_support/generate_modelsmodule.py b/build_support/generate_modelsmodule.py
index 65469b2659..fa2af8442b 100644
--- a/build_support/generate_modelsmodule.py
+++ b/build_support/generate_modelsmodule.py
@@ -241,21 +241,12 @@ def generate_modelsmodule():
with open(fname, "r") as file:
copyright_header = file.read()
- fname = "modelsmodule.cpp"
+ fname = "models.cpp"
modeldir = Path(blddir) / "models"
modeldir.mkdir(parents=True, exist_ok=True)
with open(modeldir / fname, "w") as file:
file.write(copyright_header.replace("{{file_name}}", fname))
- file.write(
- dedent(
- """
- #include "modelsmodule.h"
-
- // Generated includes
- #include "config.h"
- """
- )
- )
+ file.write('\n#include "models.h"\n\n// Generated includes\n#include "config.h"\n')
for model_type, guards_fnames in includes.items():
file.write(f"\n// {model_type.capitalize()} models\n")
@@ -265,28 +256,7 @@ def generate_modelsmodule():
file.write(f'#include "{fname}"\n')
file.write(end_guard(guards))
- file.write(
- dedent(
- """
- nest::ModelsModule::ModelsModule()
- {
- }
-
- nest::ModelsModule::~ModelsModule()
- {
- }
-
- const std::string
- nest::ModelsModule::name() const
- {
- return std::string( "NEST standard models module" );
- }
-
- void
- nest::ModelsModule::init( SLIInterpreter* )
- {"""
- )
- )
+ file.write("\nvoid nest::register_models()\n{")
for model_type, guards_mnames in models.items():
file.write(f"\n // {model_type.capitalize()} models\n")
diff --git a/cmake/WriteStaticModules_h.cmake b/cmake/WriteStaticModules_h.cmake
deleted file mode 100644
index eb6681f438..0000000000
--- a/cmake/WriteStaticModules_h.cmake
+++ /dev/null
@@ -1,68 +0,0 @@
-# cmake/WriteStaticModules_h.cmake
-#
-# 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 .
-
-# The following instructions write the file nest/static_modules.h in the
-# binary directory, aka the build directory.
-
-# write static_modules.h
-function( NEST_WRITE_STATIC_MODULE_HEADER filename )
- file( WRITE "${filename}" "#ifndef STATIC_MODULES_H\n" )
- file( APPEND "${filename}" "#define STATIC_MODULES_H\n\n" )
- file( APPEND "${filename}" "#include \"modelsmodule.h\"\n" )
-
- # when we build statically, we need to add headers and addmodule for external modules
- # just as if it were a in source module.
- if ( static-libraries AND external-modules )
- file( APPEND "${filename}" "\n// Add all external modules:\n" )
- foreach ( mod ${EXTERNAL_MODULE_INCLUDES} )
- get_filename_component( mod_header ${mod} NAME )
- file( APPEND "${filename}" "#include \"${mod_header}\"\n" )
- endforeach ()
- endif ()
- file( APPEND "${filename}" "\n// Others\n" )
- file( APPEND "${filename}" "#include \"interpret.h\"\n\n" )
-
- # start `add_static_modules` function
- file( APPEND "${filename}" "void add_static_modules( SLIInterpreter& engine )\n{\n" )
- file( APPEND "${filename}" " engine.addmodule( new nest::ModelsModule() );\n" )
-
- # when we build statically, we need to add headers and addmodule for external modules
- # just as if it were a in source module.
- if ( static-libraries AND external-modules )
- file( APPEND "${filename}" "\n // Add all external modules:\n" )
- foreach ( mod_header ${EXTERNAL_MODULE_INCLUDES} )
- # get namespace:
- file( STRINGS "${mod_header}" module_namespace_string REGEX "^namespace.*" )
- if ( NOT module_namespace_string )
- printError( "Could not find namespace in '${mod_header}'." )
- endif ()
- string( REGEX REPLACE "namespace ([a-zA-Z0-9_]+)" "\\1" module_namespace ${module_namespace_string} )
-
- # get class name
- file( STRINGS "${mod_header}" module_class_string REGEX "^class.*: public SLIModule" )
- if ( NOT module_class_string )
- printError( "Could not find class that extends SLIModule in '${mod_header}'." )
- endif ()
- string( REGEX REPLACE "class ([a-zA-Z0-9_]+) : public SLIModule" "\\1" module_class ${module_class_string} )
- file( APPEND "${filename}" " engine.addmodule( new ${module_namespace}::${module_class}() );\n" )
- endforeach ()
- endif ()
-
- file( APPEND "${filename}" "}\n\n#endif\n" )
-endfunction()
diff --git a/doc/htmldoc/developer_space/workflows/nest_with_ides.rst b/doc/htmldoc/developer_space/workflows/nest_with_ides.rst
index ef4691bc54..731c5b39a9 100644
--- a/doc/htmldoc/developer_space/workflows/nest_with_ides.rst
+++ b/doc/htmldoc/developer_space/workflows/nest_with_ides.rst
@@ -376,7 +376,6 @@ Also add the generated files:
/NEST/build/libnestutil/config.h
/NEST/build/libnestutil/sliconfig.h
- /NEST/build/nest/static_modules.h
1. On the left panel select the newly created project ``NEST-fork``, then select the created target.
diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt
index 7450ad3c5d..7892e2cfd7 100644
--- a/models/CMakeLists.txt
+++ b/models/CMakeLists.txt
@@ -18,8 +18,9 @@
# along with NEST. If not, see .
set(models_sources
- modelsmodule.h ${PROJECT_BINARY_DIR}/models/modelsmodule.cpp
+ models.h ${PROJECT_BINARY_DIR}/models/models.cpp
binary_neuron.h
+ 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
diff --git a/models/modelsmodule.h b/models/models.h
similarity index 55%
rename from models/modelsmodule.h
rename to models/models.h
index 3125f51bde..3065884cf3 100644
--- a/models/modelsmodule.h
+++ b/models/models.h
@@ -1,5 +1,5 @@
/*
- * modelsmodule.h
+ * models.h
*
* This file is part of NEST.
*
@@ -20,40 +20,21 @@
*
*/
-#ifndef MODELSMODULE_H
-#define MODELSMODULE_H
+#ifndef MODELS_H
+#define MODELS_H
-// C++ includes:
-#include
-
-// Includes from sli:
-#include "slimodule.h"
+// Includes from nestkernel:
+#include "nest.h"
namespace nest
{
/**
- * Module supplying all models that are included in the NEST release.
- *
- * First Version: June 2006
- *
- * @todo Should this be a dynamic module?
+ * Function to register all node and connection models that were
+ * selected for compilation either by using the cmake switch
+ * -Dwith-models= or as specified in the modelset given to
+ * the option -Dwith-modelset=
*/
-class ModelsModule : public SLIModule
-{
-public:
- ModelsModule();
- ~ModelsModule() override;
-
- /**
- * Initialize module by registering models with the network.
- * @param SLIInterpreter* SLI interpreter
- */
- void init( SLIInterpreter* ) override;
-
- const std::string name() const override;
-};
-
-
-} // namespace
+void register_models();
+}
#endif
diff --git a/nest/neststartup.cpp b/nest/neststartup.cpp
index 15d4d992e2..e515f62666 100644
--- a/nest/neststartup.cpp
+++ b/nest/neststartup.cpp
@@ -25,7 +25,6 @@
// Generated includes:
#include "config.h"
-#include "static_modules.h"
// Includes from libnestutil:
#include "logging_event.h"
@@ -112,9 +111,6 @@ neststartup( int* argc, char*** argv, SLIInterpreter& engine, std::string module
// NestModule extends SLI by commands for neuronal simulations
addmodule< nest::NestModule >( engine );
- // now add static modules providing components.
- add_static_modules( engine );
-
/*
* The following section concerns shared user modules and is thus only
* included if we built with libtool and libltdl.
diff --git a/nestkernel/CMakeLists.txt b/nestkernel/CMakeLists.txt
index 345bd0e3d4..693e92f111 100644
--- a/nestkernel/CMakeLists.txt
+++ b/nestkernel/CMakeLists.txt
@@ -59,7 +59,7 @@ set ( nestkernel_sources
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.h secondary_event_impl.h
slice_ring_buffer.cpp slice_ring_buffer.h
spikecounter.h spikecounter.cpp
stimulation_device.h stimulation_device.cpp
@@ -134,7 +134,7 @@ if ( HAVE_MPI )
endif ()
-# Prevent problems with Conda path substitution (see #2348)
+# Prevent problems with Conda path substitution (see #2348)
set_source_files_properties( dynamicloader.cpp PROPERTIES COMPILE_OPTIONS "-O0" )
@@ -145,7 +145,7 @@ set_target_properties( nestkernel
)
target_link_libraries( nestkernel
- nestutil sli_lib
+ nestutil sli_lib models
${LTDL_LIBRARIES} ${MPI_CXX_LIBRARIES} ${MUSIC_LIBRARIES} ${SIONLIB_LIBRARIES} ${LIBNEUROSIM_LIBRARIES} ${HDF5_LIBRARIES}
)
diff --git a/nestkernel/conn_builder.cpp b/nestkernel/conn_builder.cpp
index 18c2d2fa49..8902573b35 100644
--- a/nestkernel/conn_builder.cpp
+++ b/nestkernel/conn_builder.cpp
@@ -192,7 +192,8 @@ nest::ConnBuilder::connect()
// classes are fully constructed when the test is executed
for ( auto synapse_model_id : synapse_model_id_ )
{
- const ConnectorModel& synapse_model = kernel().model_manager.get_connection_model( synapse_model_id );
+ const ConnectorModel& synapse_model =
+ kernel().model_manager.get_connection_model( synapse_model_id, /* thread */ 0 );
const bool requires_symmetric = synapse_model.has_property( ConnectionModelProperties::REQUIRES_SYMMETRIC );
if ( requires_symmetric and not( is_symmetric() or make_symmetric_ ) )
@@ -421,7 +422,7 @@ nest::ConnBuilder::set_synapse_model_( DictionaryDatum syn_params, size_t synaps
synapse_model_id_[ synapse_indx ] = synapse_model_id;
// We need to make sure that Connect can process all synapse parameters specified.
- const ConnectorModel& synapse_model = kernel().model_manager.get_connection_model( synapse_model_id );
+ const ConnectorModel& synapse_model = kernel().model_manager.get_connection_model( synapse_model_id, /* thread */ 0 );
synapse_model.check_synapse_params( syn_params );
}
diff --git a/nestkernel/connection_manager.cpp b/nestkernel/connection_manager.cpp
index 8b5008c4a4..cb43973d51 100644
--- a/nestkernel/connection_manager.cpp
+++ b/nestkernel/connection_manager.cpp
@@ -90,27 +90,38 @@ nest::ConnectionManager::~ConnectionManager()
}
void
-nest::ConnectionManager::initialize()
+nest::ConnectionManager::initialize( const bool reset_kernel )
{
+ if ( reset_kernel )
+ {
+ keep_source_table_ = true;
+ connections_have_changed_ = false;
+ get_connections_has_been_called_ = false;
+ use_compressed_spikes_ = true;
+ stdp_eps_ = 1.0e-6;
+ min_delay_ = max_delay_ = 1;
+ sw_construction_connect.reset();
+ }
+
const size_t num_threads = kernel().vp_manager.get_num_threads();
connections_.resize( num_threads );
secondary_recv_buffer_pos_.resize( num_threads );
- keep_source_table_ = true;
- connections_have_changed_ = false;
- get_connections_has_been_called_ = false;
- use_compressed_spikes_ = true;
compressed_spike_data_.resize( 0 );
+
has_primary_connections_ = false;
check_primary_connections_.initialize( num_threads, false );
secondary_connections_exist_ = false;
check_secondary_connections_.initialize( num_threads, false );
- stdp_eps_ = 1.0e-6;
+
+ // We need to obtain this while in serial context to avoid problems when
+ // increasing the number of threads.
+ const size_t num_conn_models = kernel().model_manager.get_num_connection_models();
#pragma omp parallel
{
const size_t tid = kernel().vp_manager.get_thread_id();
- connections_[ tid ] = std::vector< ConnectorBase* >( kernel().model_manager.get_num_connection_models() );
- secondary_recv_buffer_pos_[ tid ] = std::vector< std::vector< size_t > >();
+ connections_.at( tid ) = std::vector< ConnectorBase* >( num_conn_models );
+ secondary_recv_buffer_pos_.at( tid ) = std::vector< std::vector< size_t > >();
} // of omp parallel
source_table_.initialize();
@@ -122,16 +133,10 @@ nest::ConnectionManager::initialize()
std::vector< std::vector< size_t > > tmp2( kernel().vp_manager.get_num_threads(), std::vector< size_t >() );
num_connections_.swap( tmp2 );
-
- // The following line is executed by all processes, no need to communicate
- // this change in delays.
- min_delay_ = max_delay_ = 1;
-
- sw_construction_connect.reset();
}
void
-nest::ConnectionManager::finalize()
+nest::ConnectionManager::finalize( const bool )
{
source_table_.finalize();
target_table_.finalize();
@@ -142,13 +147,6 @@ nest::ConnectionManager::finalize()
compressed_spike_data_.clear();
}
-void
-nest::ConnectionManager::change_number_of_threads()
-{
- finalize();
- initialize();
-}
-
void
nest::ConnectionManager::set_status( const DictionaryDatum& d )
{
@@ -213,7 +211,8 @@ nest::ConnectionManager::get_synapse_status( const size_t source_node_id,
DictionaryDatum dict( new Dictionary );
( *dict )[ names::source ] = source_node_id;
- ( *dict )[ names::synapse_model ] = LiteralDatum( kernel().model_manager.get_connection_model( syn_id ).get_name() );
+ ( *dict )[ names::synapse_model ] =
+ LiteralDatum( kernel().model_manager.get_connection_model( syn_id, /* thread */ 0 ).get_name() );
( *dict )[ names::target_thread ] = tid;
( *dict )[ names::synapse_id ] = syn_id;
( *dict )[ names::port ] = lcid;
@@ -1607,7 +1606,7 @@ nest::ConnectionManager::deliver_secondary_events( const size_t tid,
const synindex syn_id_end = positions_tid.size();
for ( synindex syn_id = 0; syn_id < syn_id_end; ++syn_id )
{
- const ConnectorModel& conn_model = kernel().model_manager.get_connection_model( syn_id );
+ const ConnectorModel& conn_model = kernel().model_manager.get_connection_model( syn_id, tid );
const bool supports_wfr = conn_model.has_property( ConnectionModelProperties::SUPPORTS_WFR );
if ( not called_from_wfr_update or supports_wfr )
{
@@ -1675,17 +1674,11 @@ nest::ConnectionManager::remove_disabled_connections( const size_t tid )
void
nest::ConnectionManager::resize_connections()
{
- kernel().vp_manager.assert_single_threaded();
+ kernel().vp_manager.assert_thread_parallel();
- // Resize data structures for connections between neurons
- for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid )
- {
- connections_[ tid ].resize( kernel().model_manager.get_num_connection_models() );
- source_table_.resize_sources( tid );
- }
+ connections_.at( kernel().vp_manager.get_thread_id() ).resize( kernel().model_manager.get_num_connection_models() );
- // Resize data structures for connections between neurons and
- // devices
+ source_table_.resize_sources();
target_table_devices_.resize_to_number_of_synapse_types();
}
diff --git a/nestkernel/connection_manager.h b/nestkernel/connection_manager.h
index ffb947c68b..4ffa12d0a5 100644
--- a/nestkernel/connection_manager.h
+++ b/nestkernel/connection_manager.h
@@ -76,9 +76,8 @@ class ConnectionManager : public ManagerInterface
ConnectionManager();
~ConnectionManager() override;
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/connector_model_impl.h b/nestkernel/connector_model_impl.h
index 5de25ec15a..73a3969508 100644
--- a/nestkernel/connector_model_impl.h
+++ b/nestkernel/connector_model_impl.h
@@ -38,6 +38,7 @@
#include "kernel_manager.h"
#include "nest_time.h"
#include "nest_timeconverter.h"
+#include "secondary_event_impl.h"
// Includes from sli:
#include "dictutils.h"
diff --git a/nestkernel/event.cpp b/nestkernel/event.cpp
index 6af31424d9..587153505b 100644
--- a/nestkernel/event.cpp
+++ b/nestkernel/event.cpp
@@ -25,6 +25,7 @@
// Includes from nestkernel:
#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 c87c791f0b..a568df519c 100644
--- a/nestkernel/event_delivery_manager.cpp
+++ b/nestkernel/event_delivery_manager.cpp
@@ -76,25 +76,30 @@ EventDeliveryManager::~EventDeliveryManager()
}
void
-EventDeliveryManager::initialize()
+EventDeliveryManager::initialize( const bool reset_kernel )
{
+ if ( reset_kernel )
+ {
+ init_moduli();
+ reset_timers_for_preparation();
+ reset_timers_for_dynamics();
+
+ // Ensures that ResetKernel resets off_grid_spiking_
+ off_grid_spiking_ = false;
+ buffer_size_target_data_has_changed_ = false;
+ send_recv_buffer_shrink_limit_ = 0.2;
+ send_recv_buffer_shrink_spare_ = 0.1;
+ send_recv_buffer_grow_extra_ = 0.5;
+ send_recv_buffer_resize_log_.clear();
+ }
+
const size_t num_threads = kernel().vp_manager.get_num_threads();
- init_moduli();
local_spike_counter_.resize( num_threads, 0 );
reset_counters();
- reset_timers_for_preparation();
- reset_timers_for_dynamics();
emitted_spikes_register_.resize( num_threads );
off_grid_emitted_spikes_register_.resize( num_threads );
gather_completed_checker_.initialize( num_threads, false );
- // Ensures that ResetKernel resets off_grid_spiking_
- off_grid_spiking_ = false;
- buffer_size_target_data_has_changed_ = false;
- send_recv_buffer_shrink_limit_ = 0.2;
- send_recv_buffer_shrink_spare_ = 0.1;
- send_recv_buffer_grow_extra_ = 0.5;
- send_recv_buffer_resize_log_.clear();
#pragma omp parallel
{
@@ -113,7 +118,7 @@ EventDeliveryManager::initialize()
}
void
-EventDeliveryManager::finalize()
+EventDeliveryManager::finalize( const bool )
{
// clear the spike buffers
for ( auto& vec_spikedata_ptr : emitted_spikes_register_ )
@@ -136,13 +141,6 @@ EventDeliveryManager::finalize()
recv_buffer_off_grid_spike_data_.clear();
}
-void
-EventDeliveryManager::change_number_of_threads()
-{
- finalize();
- initialize();
-}
-
void
EventDeliveryManager::set_status( const DictionaryDatum& dict )
{
diff --git a/nestkernel/event_delivery_manager.h b/nestkernel/event_delivery_manager.h
index fc92ce720e..4f49645077 100644
--- a/nestkernel/event_delivery_manager.h
+++ b/nestkernel/event_delivery_manager.h
@@ -63,9 +63,8 @@ class EventDeliveryManager : public ManagerInterface
EventDeliveryManager();
~EventDeliveryManager() override;
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/io_manager.cpp b/nestkernel/io_manager.cpp
index 6db6f54a72..f4552a6c30 100644
--- a/nestkernel/io_manager.cpp
+++ b/nestkernel/io_manager.cpp
@@ -132,24 +132,27 @@ IOManager::set_data_path_prefix_( const DictionaryDatum& dict )
}
void
-IOManager::initialize()
+IOManager::initialize( const bool reset_kernel )
{
- DictionaryDatum dict( new Dictionary );
- // The properties data_path and data_prefix can be set via environment variables
- char* data_path = std::getenv( "NEST_DATA_PATH" );
- if ( data_path )
+ if ( reset_kernel )
{
- ( *dict )[ names::data_path ] = std::string( data_path );
- }
- char* data_prefix = std::getenv( "NEST_DATA_PREFIX" );
- if ( data_prefix )
- {
- ( *dict )[ names::data_prefix ] = std::string( data_prefix );
- }
+ DictionaryDatum dict( new Dictionary );
+ // The properties data_path and data_prefix can be set via environment variables
+ char* data_path = std::getenv( "NEST_DATA_PATH" );
+ if ( data_path )
+ {
+ ( *dict )[ names::data_path ] = std::string( data_path );
+ }
+ char* data_prefix = std::getenv( "NEST_DATA_PREFIX" );
+ if ( data_prefix )
+ {
+ ( *dict )[ names::data_prefix ] = std::string( data_prefix );
+ }
- set_data_path_prefix_( dict );
+ set_data_path_prefix_( dict );
- overwrite_files_ = false;
+ overwrite_files_ = false;
+ }
for ( const auto& it : recording_backends_ )
{
@@ -162,30 +165,15 @@ IOManager::initialize()
}
void
-IOManager::finalize()
-{
- for ( const auto& it : recording_backends_ )
- {
- it.second->finalize();
- }
- for ( const auto& it : stimulation_backends_ )
- {
- it.second->finalize();
- }
-}
-
-void
-IOManager::change_number_of_threads()
+IOManager::finalize( const bool )
{
for ( const auto& it : recording_backends_ )
{
it.second->finalize();
- it.second->initialize();
}
for ( const auto& it : stimulation_backends_ )
{
it.second->finalize();
- it.second->initialize();
}
}
diff --git a/nestkernel/io_manager.h b/nestkernel/io_manager.h
index 7aedbbc213..ea4be311bd 100644
--- a/nestkernel/io_manager.h
+++ b/nestkernel/io_manager.h
@@ -51,9 +51,8 @@ class IOManager : public ManagerInterface
IOManager();
~IOManager() override;
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/kernel_manager.cpp b/nestkernel/kernel_manager.cpp
index bc99259b32..1a34248ef3 100644
--- a/nestkernel/kernel_manager.cpp
+++ b/nestkernel/kernel_manager.cpp
@@ -27,7 +27,7 @@ nest::KernelManager* nest::KernelManager::kernel_manager_instance_ = nullptr;
void
nest::KernelManager::create_kernel_manager()
{
-#pragma omp critical( create_kernel_manager )
+#pragma omp master
{
if ( not kernel_manager_instance_ )
{
@@ -35,6 +35,7 @@ nest::KernelManager::create_kernel_manager()
assert( kernel_manager_instance_ );
}
}
+#pragma omp barrier
}
void
@@ -65,10 +66,10 @@ nest::KernelManager::KernelManager()
&random_manager,
&simulation_manager,
&modelrange_manager,
- &model_manager,
&connection_manager,
&sp_manager,
&event_delivery_manager,
+ &model_manager,
&music_manager,
&io_manager,
&node_manager } )
@@ -141,10 +142,18 @@ 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 )
+ {
+ ( *mgr_it )->finalize( /* reset_kernel */ false );
+ }
+
vp_manager.set_num_threads( new_num_threads );
+
+ // Initialize in original order with new number of threads set
for ( auto& manager : managers )
{
- manager->change_number_of_threads();
+ manager->initialize( /* reset_kernel */ false );
}
}
diff --git a/nestkernel/logging_manager.cpp b/nestkernel/logging_manager.cpp
index 9031716a23..bbc99211e5 100644
--- a/nestkernel/logging_manager.cpp
+++ b/nestkernel/logging_manager.cpp
@@ -42,13 +42,16 @@ nest::LoggingManager::LoggingManager()
}
void
-nest::LoggingManager::initialize()
+nest::LoggingManager::initialize( const bool reset_kernel )
{
- dict_miss_is_error_ = true;
+ if ( reset_kernel )
+ {
+ dict_miss_is_error_ = true;
+ }
}
void
-nest::LoggingManager::finalize()
+nest::LoggingManager::finalize( const bool )
{
}
diff --git a/nestkernel/logging_manager.h b/nestkernel/logging_manager.h
index b2a05fd9c6..3dc44a3677 100644
--- a/nestkernel/logging_manager.h
+++ b/nestkernel/logging_manager.h
@@ -49,8 +49,8 @@ class LoggingManager : public ManagerInterface
public:
LoggingManager();
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/manager_interface.h b/nestkernel/manager_interface.h
index 71b217c2e3..5dc04f8f7a 100644
--- a/nestkernel/manager_interface.h
+++ b/nestkernel/manager_interface.h
@@ -68,9 +68,11 @@ class ManagerInterface
* is responsible for calling the initialization routines on the
* specific managers in correct order.
*
+ * @param reset_kernel Pass false if calling from kernel_manager::change_number_of_threads() to limit operations
+ *
* @see finalize()
*/
- virtual void initialize() = 0;
+ virtual void initialize( const bool reset_kernel = true ) = 0;
/**
* Take down manager after operation.
@@ -85,19 +87,11 @@ class ManagerInterface
* specific managers in correct order, i.e., the opposite order of
* initialize() calls.
*
- * @see initialize()
- */
- virtual void finalize() = 0;
-
- /**
- * Change the number of threads
+ * @param reset_kernel pass false if calling from kernel_manager::change_number_of_threads() to limit operations
*
- * Many data structures within the different managers depend on the
- * number of threads. This function is called on each manager upon a
- * change of that number and allows the manager to re-allocate data
- * structures accordingly.
+ * @see initialize()
*/
- virtual void change_number_of_threads() {};
+ virtual void finalize( const bool reset_kernel = true ) = 0;
/**
* Set the status of the manager
diff --git a/nestkernel/model_manager.cpp b/nestkernel/model_manager.cpp
index 8c7a9eca00..3e222520bd 100644
--- a/nestkernel/model_manager.cpp
+++ b/nestkernel/model_manager.cpp
@@ -38,14 +38,15 @@
#include "proxynode.h"
#include "vp_manager_impl.h"
+// Includes from models:
+#include "models.h"
+
namespace nest
{
ModelManager::ModelManager()
- : builtin_node_models_()
- , node_models_()
- , builtin_connection_models_()
+ : node_models_()
, connection_models_()
, modeldict_( new Dictionary )
, synapsedict_( new Dictionary )
@@ -58,26 +59,11 @@ ModelManager::ModelManager()
ModelManager::~ModelManager()
{
clear_connection_models_();
- for ( auto&& connection_model : builtin_connection_models_ )
- {
- if ( connection_model )
- {
- delete connection_model;
- }
- }
-
clear_node_models_();
- for ( auto&& node_model : builtin_node_models_ )
- {
- if ( node_model )
- {
- delete node_model;
- }
- }
}
void
-ModelManager::initialize()
+ModelManager::initialize( const bool )
{
if ( not proxynode_model_ )
{
@@ -86,74 +72,34 @@ ModelManager::initialize()
proxynode_model_->set_threads();
}
- // Re-create the node model list from the clean prototypes
- for ( size_t i = 0; i < builtin_node_models_.size(); ++i )
- {
- // set the number of threads for the number of sli pools
- builtin_node_models_[ i ]->set_threads();
- std::string name = builtin_node_models_[ i ]->get_name();
- node_models_.push_back( builtin_node_models_[ i ]->clone( name ) );
- modeldict_->insert( name, i );
- }
-
- // Create proxy nodes, one for each thread and model
- proxy_nodes_.resize( kernel().vp_manager.get_num_threads() );
-
-#pragma omp parallel
- {
- const size_t t = kernel().vp_manager.get_thread_id();
- proxy_nodes_[ t ].clear();
-
- for ( auto&& builtin_node_model : builtin_node_models_ )
- {
- const int model_id = builtin_node_model->get_model_id();
- proxy_nodes_[ t ].push_back( create_proxynode_( t, model_id ) );
- }
- }
-
- synapsedict_->clear();
-
- // one list of prototypes per thread
- std::vector< std::vector< ConnectorModel* > > tmp_proto( kernel().vp_manager.get_num_threads() );
- connection_models_.swap( tmp_proto );
+ const size_t num_threads = kernel().vp_manager.get_num_threads();
- // (re-)append all synapse prototypes
- for ( auto&& connection_model : builtin_connection_models_ )
- {
- if ( connection_model )
- {
- std::string name = connection_model->get_name();
- const synindex syn_id = connection_models_[ 0 ].size();
+ // Make space for one vector of connection models per thread
+ connection_models_.resize( num_threads );
- for ( size_t t = 0; t < static_cast< size_t >( kernel().vp_manager.get_num_threads() ); ++t )
- {
- connection_models_[ t ].push_back( connection_model->clone( name, syn_id ) );
- }
+ // Make space for one vector of proxynodes for each thread
+ proxy_nodes_.resize( num_threads );
- synapsedict_->insert( name, syn_id );
- }
- }
+ register_models();
}
void
-ModelManager::finalize()
+ModelManager::finalize( const bool )
{
clear_node_models_();
clear_connection_models_();
+}
- // We free all Node memory
- for ( auto& node_model : builtin_node_models_ )
+size_t
+ModelManager::get_num_connection_models() const
+{
+ // For the case when the ModelManager is not yet fully initialized
+ if ( connection_models_.empty() )
{
- // delete all nodes, because cloning the model may have created instances.
- node_model->clear();
+ return 0;
}
-}
-void
-ModelManager::change_number_of_threads()
-{
- finalize();
- initialize();
+ return connection_models_.at( kernel().vp_manager.get_thread_id() ).size();
}
void
@@ -182,7 +128,7 @@ ModelManager::get_status( DictionaryDatum& dict )
def< int >( dict, names::max_num_syn_models, MAX_SYN_ID + 1 );
}
-size_t
+void
ModelManager::copy_model( Name old_name, Name new_name, DictionaryDatum params )
{
if ( modeldict_->known( new_name ) or synapsedict_->known( new_name ) )
@@ -193,41 +139,35 @@ ModelManager::copy_model( Name old_name, Name new_name, DictionaryDatum params )
const Token oldnodemodel = modeldict_->lookup( old_name );
const Token oldsynmodel = synapsedict_->lookup( old_name );
- size_t new_id;
if ( not oldnodemodel.empty() )
{
- size_t old_id = static_cast< size_t >( oldnodemodel );
- new_id = copy_node_model_( old_id, new_name );
- set_node_defaults_( new_id, params );
+ const size_t old_id = static_cast< size_t >( oldnodemodel );
+ copy_node_model_( old_id, new_name, params );
}
else if ( not oldsynmodel.empty() )
{
- size_t old_id = static_cast< size_t >( oldsynmodel );
- new_id = copy_connection_model_( old_id, new_name );
- set_synapse_defaults_( new_id, params );
+ const size_t old_id = static_cast< size_t >( oldsynmodel );
+ copy_connection_model_( old_id, new_name, params );
}
else
{
throw UnknownModelName( old_name );
}
-
- return new_id;
}
size_t
ModelManager::register_node_model_( Model* model )
{
+ assert( model );
+
const size_t id = node_models_.size();
const std::string name = model->get_name();
model->set_model_id( id );
model->set_type_id( id );
- builtin_node_models_.push_back( model );
-
- Model* cloned_model = model->clone( name );
- cloned_model->set_model_id( id );
- node_models_.push_back( cloned_model );
+ model->set_threads();
+ node_models_.push_back( model );
modeldict_->insert( name, id );
#pragma omp parallel
@@ -239,8 +179,8 @@ ModelManager::register_node_model_( Model* model )
return id;
}
-size_t
-ModelManager::copy_node_model_( size_t old_id, Name new_name )
+void
+ModelManager::copy_node_model_( const size_t old_id, Name new_name, DictionaryDatum params )
{
Model* old_model = get_node_model( old_id );
old_model->deprecation_warning( "CopyModel" );
@@ -252,19 +192,21 @@ ModelManager::copy_node_model_( size_t old_id, Name new_name )
node_models_.push_back( new_model );
modeldict_->insert( new_name, new_id );
+ set_node_defaults_( new_id, params );
+
#pragma omp parallel
{
const size_t t = kernel().vp_manager.get_thread_id();
proxy_nodes_[ t ].push_back( create_proxynode_( t, new_id ) );
}
-
- return new_id;
}
-size_t
-ModelManager::copy_connection_model_( size_t old_id, Name new_name )
+void
+ModelManager::copy_connection_model_( const size_t old_id, Name new_name, DictionaryDatum params )
{
- size_t new_id = connection_models_[ 0 ].size();
+ kernel().vp_manager.assert_single_threaded();
+
+ const size_t new_id = connection_models_.at( kernel().vp_manager.get_thread_id() ).size();
if ( new_id == invalid_synindex )
{
@@ -273,17 +215,19 @@ ModelManager::copy_connection_model_( size_t old_id, Name new_name )
LOG( M_ERROR, "ModelManager::copy_connection_model_", msg );
throw KernelException( "Synapse model count exceeded" );
}
- assert( new_id != invalid_synindex );
+ synapsedict_->insert( new_name, new_id );
- for ( size_t t = 0; t < static_cast< size_t >( kernel().vp_manager.get_num_threads() ); ++t )
+
+#pragma omp parallel
{
- connection_models_[ t ].push_back( get_connection_model( old_id ).clone( new_name.toString(), new_id ) );
- }
+ const size_t thread_id = kernel().vp_manager.get_thread_id();
+ connection_models_.at( thread_id )
+ .push_back( get_connection_model( old_id, thread_id ).clone( new_name.toString(), new_id ) );
- synapsedict_->insert( new_name, new_id );
+ kernel().connection_manager.resize_connections();
+ }
- kernel().connection_manager.resize_connections();
- return new_id;
+ set_synapse_defaults_( new_id, params ); // handles parallelism internally
}
@@ -412,13 +356,11 @@ ModelManager::get_connector_defaults( synindex syn_id ) const
void
ModelManager::clear_node_models_()
{
- // We delete all models, which will also delete all nodes. The
- // built-in models will be recovered from the builtin_node_models_ in
- // init()
- for ( auto&& node_model : node_models_ )
+ for ( const auto& node_model : node_models_ )
{
if ( node_model )
{
+ node_model->clear(); // Make sure all node memory is gone
delete node_model;
}
}
@@ -439,7 +381,7 @@ ModelManager::clear_connection_models_()
{
for ( size_t t = 0; t < connection_models_.size(); ++t )
{
- for ( auto&& connection_model : connection_models_[ t ] )
+ for ( const auto& connection_model : connection_models_[ t ] )
{
if ( connection_model )
{
@@ -455,6 +397,7 @@ ModelManager::clear_connection_models_()
connection_models_[ t ].clear();
}
connection_models_.clear();
+ synapsedict_->clear();
}
void
@@ -520,34 +463,6 @@ ModelManager::memory_info() const
std::cout.unsetf( std::ios::left );
}
-synindex
-ModelManager::register_connection_model_( ConnectorModel* cf )
-{
- if ( synapsedict_->known( cf->get_name() ) )
- {
- std::string msg =
- String::compose( "A synapse type called '%1' already exists.\nPlease choose a different name!", cf->get_name() );
- delete cf;
- throw NamingConflict( msg );
- }
-
- builtin_connection_models_.push_back( cf );
-
- const synindex syn_id = connection_models_[ 0 ].size();
- for ( size_t t = 0; t < static_cast< size_t >( kernel().vp_manager.get_num_threads() ); ++t )
- {
- connection_models_[ t ].push_back( cf->clone( cf->get_name(), syn_id ) );
- }
-
- synapsedict_->insert( cf->get_name(), syn_id );
-
- // Need to resize Connector vectors in case connection model is added after
- // ConnectionManager is initialised.
- kernel().connection_manager.resize_connections();
-
- return syn_id;
-}
-
Node*
ModelManager::create_proxynode_( size_t t, int model_id )
{
diff --git a/nestkernel/model_manager.h b/nestkernel/model_manager.h
index a9df8a645c..dc816bb815 100644
--- a/nestkernel/model_manager.h
+++ b/nestkernel/model_manager.h
@@ -49,9 +49,8 @@ class ModelManager : public ManagerInterface
ModelManager();
~ModelManager() override;
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
@@ -82,7 +81,7 @@ class ModelManager : public ManagerInterface
* num_connections and the min_ and max_delay setting in
* ConnectorBase was moved out to the ConnectionManager
*/
- ConnectorModel& get_connection_model( synindex syn_id, size_t t = 0 );
+ ConnectorModel& get_connection_model( synindex syn_id, size_t thread_id );
const std::vector< ConnectorModel* >& get_connection_models( size_t tid );
@@ -96,11 +95,28 @@ class ModelManager : public ManagerInterface
* @param deprecation_info If non-empty string, deprecation warning will
* be issued for model with this info to user.
* @return ID of the new model object.
- * @see register_prototype_connection
+ * @see register_connection_model
*/
template < class ModelT >
size_t register_node_model( const Name& name, std::string deprecation_info = std::string() );
+ /**
+ * Register a synape model with a custom Connector model and without any
+ * common properties.
+ *
+ * "hpc synapses" use `TargetIdentifierIndex` for `ConnectionT` and store
+ * the target neuron in form of a 2 Byte index instead of an 8 Byte pointer.
+ * This limits the number of thread local neurons to 65,536. No support for
+ * different receptor types. Otherwise identical to non-hpc version.
+ *
+ * When called, this function should be specialised by a class template,
+ * e.g. `bernoulli_synapse< targetidentifierT >`
+ *
+ * @param name The name under which the ConnectorModel will be registered.
+ */
+ template < template < typename targetidentifierT > class ConnectionT >
+ void register_connection_model( const std::string& name );
+
/**
* Copy an existing model and register it as a new model.
*
@@ -108,10 +124,9 @@ class ModelManager : public ManagerInterface
* @param old_name name of existing model.
* @param new_name name of new model.
* @param params default parameters of new model.
- * @return model ID of new Model object.
* @see copy_node_model_, copy_connection_model_
*/
- size_t copy_model( Name old_name, Name new_name, DictionaryDatum params );
+ void copy_model( Name old_name, Name new_name, DictionaryDatum params );
/**
* Set the default parameters of a model.
@@ -123,23 +138,6 @@ class ModelManager : public ManagerInterface
*/
bool set_model_defaults( Name name, DictionaryDatum params );
- /**
- * Register a synape model with a custom Connector model and without any
- * common properties.
- *
- * "hpc synapses" use `TargetIdentifierIndex` for `ConnectionT` and store
- * the target neuron in form of a 2 Byte index instead of an 8 Byte pointer.
- * This limits the number of thread local neurons to 65,536. No support for
- * different receptor types. Otherwise identical to non-hpc version.
- *
- * When called, this function should be specialised by a class template,
- * e.g. `bernoulli_synapse< targetidentifierT >`
- *
- * @param name The name under which the ConnectorModel will be registered.
- */
- template < template < typename targetidentifierT > class ConnectionT >
- void register_connection_model( const std::string& name );
-
/**
* @return The model ID for a Model with a given name
* @throws UnknownModelName if the model is not available
@@ -179,33 +177,39 @@ class ModelManager : public ManagerInterface
SecondaryEvent& get_secondary_event_prototype( const synindex syn_id, const size_t tid );
private:
+ /**
+ * Delete all models and clear the modeldict
+ *
+ * This function deletes all models, which will as a side-effect also
+ * delete all nodes. The built-in models will be re-registered in
+ * initialize()
+ */
void clear_node_models_();
void clear_connection_models_();
size_t register_node_model_( Model* model );
- synindex register_connection_model_( ConnectorModel* );
+ template < typename CompleteConnecionT >
+ void register_specific_connection_model_( const std::string& name );
/**
* Copy an existing node model and register it as a new model.
*
* @param old_id ID of existing model.
* @param new_name name of new model.
- * @return model ID of new Model object.
* @see copy_model(), copy_connection_model_()
*/
- size_t copy_node_model_( size_t old_id, Name new_name );
+ void copy_node_model_( const size_t old_id, Name new_name, DictionaryDatum params );
/**
* Copy an existing synapse model and register it as a new model.
*
* @param old_id ID of existing model.
* @param new_name name of new model.
- * @return model ID of new Model object.
* @see copy_model(), copy_node_model_()
*/
- size_t copy_connection_model_( size_t old_id, Name new_name );
+ void copy_connection_model_( const size_t old_id, Name new_name, DictionaryDatum params );
/**
* Set the default parameters of a model.
@@ -229,34 +233,40 @@ class ModelManager : public ManagerInterface
static bool compare_model_by_id_( const int a, const int b );
/**
- * List of clean built-in node models.
- */
- std::vector< Model* > builtin_node_models_;
-
- /**
- * List of usable node models. This list is cleared and repopulated
- * upon application startup and calls to ResetKernel.
+ * List of node models.
+ *
+ * The list contains all built-in node models requested for
+ * compilation using -Dwith-models or -Dwith-modelset, models
+ * registered from within extension modules, and models created by
+ * calls to CopyModel().
+ *
+ * This list is cleared and built-in models are re-registered upon
+ * calls to ResetKernel, while those registered from user-modules
+ * and copies are not.
*
- * It contains copies of the built-in models, models registered from extension
- * modules, and models created by calls to CopyModel(). The elements
- * of this list also keep the user-modified defaults.
+ * The elements of this list are used to create instances and are
+ * responsible for the storage of model defaults.
*/
std::vector< Model* > node_models_;
/**
- * List of built-in clean connection models.
- */
- std::vector< ConnectorModel* > builtin_connection_models_;
-
- /**
- * The list of usable connection models.
+ * The list of connection models.
*
- * The first dimension keeps one entry per thread, the second dimension has the actual models.
- * This list is cleared and repopulated upon application startup and
- * calls to ResetKernel. The inner list contains copies of the
- * built-in models, models registered from extension modules, and
- * models created by calls to CopyModel(). The elements of the list
- * also keep the user-modified defaults.
+ * This list contains all built-in connection models requested for
+ * compilation using -Dwith-models or -Dwith-modelset, models
+ * registered from within extension modules, and models created by
+ * calls to CopyModel().
+ *
+ * The first dimension is thread-optimitzed by containing one vector
+ * with all models per thread, as to avoid colliding memory accesses
+ * during connection creation.
+ *
+ * This list is cleared and built-in models are re-registered upon
+ * calls to ResetKernel, while those registered from user-modules
+ * and copies are not.
+ *
+ * The elements of this list are used to create instances and are
+ * responsible for the storage of model defaults.
*/
std::vector< std::vector< ConnectorModel* > > connection_models_;
@@ -288,10 +298,10 @@ ModelManager::are_model_defaults_modified() const
}
inline ConnectorModel&
-ModelManager::get_connection_model( synindex syn_id, size_t t )
+ModelManager::get_connection_model( synindex syn_id, size_t thread_id )
{
assert_valid_syn_id( syn_id );
- return *( connection_models_[ t ][ syn_id ] );
+ return *( connection_models_[ thread_id ][ syn_id ] );
}
inline const std::vector< ConnectorModel* >&
@@ -300,13 +310,6 @@ ModelManager::get_connection_models( size_t tid )
return connection_models_[ tid ];
}
-inline size_t
-ModelManager::get_num_connection_models() const
-{
- assert( connection_models_[ 0 ].size() <= invalid_synindex );
- return connection_models_[ 0 ].size();
-}
-
inline void
ModelManager::assert_valid_syn_id( synindex syn_id, size_t t ) const
{
diff --git a/nestkernel/model_manager_impl.h b/nestkernel/model_manager_impl.h
index 5c539e0bcc..d9e8d8e6c7 100644
--- a/nestkernel/model_manager_impl.h
+++ b/nestkernel/model_manager_impl.h
@@ -57,23 +57,58 @@ template < template < typename targetidentifierT > class ConnectionT >
void
ModelManager::register_connection_model( const std::string& name )
{
- // register normal version of the synapse
- ConnectorModel* cf = new GenericConnectorModel< ConnectionT< TargetIdentifierPtrRport > >( name );
- register_connection_model_( cf );
+ // Required to check which variants to create
+ ConnectorModel const* const dummy_model =
+ new GenericConnectorModel< ConnectionT< TargetIdentifierPtrRport > >( "dummy" );
- // register the "hpc" version with the same parameters but a different target identifier
- if ( cf->has_property( ConnectionModelProperties::SUPPORTS_HPC ) )
+ register_specific_connection_model_< ConnectionT< TargetIdentifierPtrRport > >( name );
+ if ( dummy_model->has_property( ConnectionModelProperties::SUPPORTS_HPC ) )
{
- cf = new GenericConnectorModel< ConnectionT< TargetIdentifierIndex > >( name + "_hpc" );
- register_connection_model_( cf );
+ 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();
- // register the "lbl" (labeled) version with the same parameters but a different connection type
- if ( cf->has_property( ConnectionModelProperties::SUPPORTS_LBL ) )
+ if ( synapsedict_->known( name ) )
{
- cf = new GenericConnectorModel< ConnectionLabel< ConnectionT< TargetIdentifierPtrRport > > >( name + "_lbl" );
- register_connection_model_( cf );
+ 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*
diff --git a/nestkernel/modelrange_manager.cpp b/nestkernel/modelrange_manager.cpp
index 4b578e22c6..11c5c8b3ed 100644
--- a/nestkernel/modelrange_manager.cpp
+++ b/nestkernel/modelrange_manager.cpp
@@ -41,12 +41,12 @@ ModelRangeManager::ModelRangeManager()
}
void
-ModelRangeManager::initialize()
+ModelRangeManager::initialize( const bool )
{
}
void
-ModelRangeManager::finalize()
+ModelRangeManager::finalize( const bool )
{
modelranges_.clear();
first_node_id_ = 0;
diff --git a/nestkernel/modelrange_manager.h b/nestkernel/modelrange_manager.h
index be021dff6d..c25941325f 100644
--- a/nestkernel/modelrange_manager.h
+++ b/nestkernel/modelrange_manager.h
@@ -45,8 +45,8 @@ class ModelRangeManager : public ManagerInterface
{
}
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/mpi_manager.cpp b/nestkernel/mpi_manager.cpp
index 784d28178a..591aecb17f 100644
--- a/nestkernel/mpi_manager.cpp
+++ b/nestkernel/mpi_manager.cpp
@@ -178,8 +178,13 @@ nest::MPIManager::init_mpi( int* argc, char** argv[] )
#endif /* #ifdef HAVE_MPI */
void
-nest::MPIManager::initialize()
+nest::MPIManager::initialize( const bool reset_kernel )
{
+ if ( not reset_kernel )
+ {
+ return;
+ }
+
#ifndef HAVE_MPI
char* pmix_rank_set = std::getenv( "PMIX_RANK" ); // set by OpenMPI's launcher
char* pmi_rank_set = std::getenv( "PMI_RANK" ); // set by MPICH's launcher
@@ -211,7 +216,7 @@ nest::MPIManager::initialize()
}
void
-nest::MPIManager::finalize()
+nest::MPIManager::finalize( const bool )
{
}
diff --git a/nestkernel/mpi_manager.h b/nestkernel/mpi_manager.h
index c644731f4b..58d7d30423 100644
--- a/nestkernel/mpi_manager.h
+++ b/nestkernel/mpi_manager.h
@@ -65,8 +65,8 @@ class MPIManager : public ManagerInterface
{
}
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/music_manager.cpp b/nestkernel/music_manager.cpp
index 3e89c1e548..2aa652adb7 100644
--- a/nestkernel/music_manager.cpp
+++ b/nestkernel/music_manager.cpp
@@ -48,8 +48,13 @@ MUSICManager::MUSICManager()
}
void
-MUSICManager::initialize()
+MUSICManager::initialize( const bool reset_kernel )
{
+ if ( not reset_kernel )
+ {
+ return;
+ }
+
#ifdef HAVE_MUSIC
// Reset music_in_portlist_ to its pristine state.
// See comment above pristine_music_in_portlist_ in the header.
@@ -58,7 +63,7 @@ MUSICManager::initialize()
}
void
-MUSICManager::finalize()
+MUSICManager::finalize( const bool )
{
}
diff --git a/nestkernel/music_manager.h b/nestkernel/music_manager.h
index 5aa5a20dd8..c53b1891b1 100644
--- a/nestkernel/music_manager.h
+++ b/nestkernel/music_manager.h
@@ -51,8 +51,8 @@ namespace nest
class MUSICManager : public ManagerInterface
{
public:
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/node_manager.cpp b/nestkernel/node_manager.cpp
index df29f1908e..d3155c701d 100644
--- a/nestkernel/node_manager.cpp
+++ b/nestkernel/node_manager.cpp
@@ -37,6 +37,7 @@
#include "model.h"
#include "model_manager_impl.h"
#include "node.h"
+#include "secondary_event_impl.h"
#include "vp_manager.h"
#include "vp_manager_impl.h"
@@ -67,7 +68,7 @@ NodeManager::~NodeManager()
}
void
-NodeManager::initialize()
+NodeManager::initialize( const bool reset_kernel )
{
// explicitly force construction of wfr_nodes_vec_ to ensure consistent state
wfr_network_size_ = 0;
@@ -75,24 +76,19 @@ NodeManager::initialize()
num_thread_local_devices_.resize( kernel().vp_manager.get_num_threads(), 0 );
ensure_valid_thread_local_ids();
- sw_construction_create_.reset();
+ if ( reset_kernel )
+ {
+ sw_construction_create_.reset();
+ }
}
void
-NodeManager::finalize()
+NodeManager::finalize( const bool )
{
destruct_nodes_();
clear_node_collection_container();
}
-void
-NodeManager::change_number_of_threads()
-{
- // No nodes exist at this point, so nothing to tear down. See
- // checks for node_manager.size() in VPManager::set_status()
- initialize();
-}
-
DictionaryDatum
NodeManager::get_status( size_t idx )
{
@@ -179,7 +175,12 @@ NodeManager::add_node( size_t model_id, long n )
// resize the target table for delivery of events to devices to make sure the first dimension
// matches the number of local nodes and the second dimension matches number of synapse types
kernel().connection_manager.resize_target_table_devices_to_number_of_neurons();
- kernel().connection_manager.resize_target_table_devices_to_number_of_synapse_types();
+
+#pragma omp parallel
+ {
+ // must be called in parallel context to properly configure per-thread data structures
+ kernel().connection_manager.resize_target_table_devices_to_number_of_synapse_types();
+ }
sw_construction_create_.stop();
diff --git a/nestkernel/node_manager.h b/nestkernel/node_manager.h
index 4016c258ba..def97d9e60 100644
--- a/nestkernel/node_manager.h
+++ b/nestkernel/node_manager.h
@@ -52,9 +52,8 @@ class NodeManager : public ManagerInterface
NodeManager();
~NodeManager() override;
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/per_thread_bool_indicator.cpp b/nestkernel/per_thread_bool_indicator.cpp
index 8c754887a7..2028574ff4 100644
--- a/nestkernel/per_thread_bool_indicator.cpp
+++ b/nestkernel/per_thread_bool_indicator.cpp
@@ -22,6 +22,9 @@
#include "per_thread_bool_indicator.h"
+// Includes from nestkernel
+#include "kernel_manager.h"
+
namespace nest
{
@@ -44,7 +47,7 @@ PerThreadBoolIndicator::operator[]( const size_t tid )
void
PerThreadBoolIndicator::initialize( const size_t num_threads, const bool status )
{
- VPManager::assert_single_threaded();
+ kernel().vp_manager.assert_single_threaded();
per_thread_status_.clear();
per_thread_status_.resize( num_threads, BoolIndicatorUInt64( status ) );
}
diff --git a/nestkernel/random_manager.cpp b/nestkernel/random_manager.cpp
index 6a2a65ce77..dd52f43b2a 100644
--- a/nestkernel/random_manager.cpp
+++ b/nestkernel/random_manager.cpp
@@ -57,55 +57,49 @@ nest::RandomManager::RandomManager()
nest::RandomManager::~RandomManager()
{
- finalize();
}
void
-nest::RandomManager::initialize()
+nest::RandomManager::initialize( const bool reset_kernel )
{
- register_rng_type< std::mt19937 >( "mt19937" );
- register_rng_type< std::mt19937_64 >( "mt19937_64" );
+ if ( reset_kernel )
+ {
+ register_rng_type< std::mt19937 >( "mt19937" );
+ register_rng_type< std::mt19937_64 >( "mt19937_64" );
#ifdef HAVE_RANDOM123
- register_rng_type< r123::Engine< r123::Philox4x32 > >( "Philox_32" );
+ register_rng_type< r123::Engine< r123::Philox4x32 > >( "Philox_32" );
#if R123_USE_PHILOX_64BIT
- register_rng_type< r123::Engine< r123::Philox4x64 > >( "Philox_64" );
+ register_rng_type< r123::Engine< r123::Philox4x64 > >( "Philox_64" );
#endif
- register_rng_type< r123::Engine< r123::Threefry4x32 > >( "Threefry_32" );
+ register_rng_type< r123::Engine< r123::Threefry4x32 > >( "Threefry_32" );
#if R123_USE_64BIT
- register_rng_type< r123::Engine< r123::Threefry4x64 > >( "Threefry_64" );
+ register_rng_type< r123::Engine< r123::Threefry4x64 > >( "Threefry_64" );
#endif
#endif
- current_rng_type_ = DEFAULT_RNG_TYPE_;
- base_seed_ = DEFAULT_BASE_SEED_;
+ current_rng_type_ = DEFAULT_RNG_TYPE_;
+ base_seed_ = DEFAULT_BASE_SEED_;
+ }
- reset_rngs_();
-}
+ // Create new RNGs of the currently used RNG type.
+ rank_synced_rng_ = rng_types_[ current_rng_type_ ]->create( { base_seed_, RANK_SYNCED_SEEDER_ } );
-void
-nest::RandomManager::finalize()
-{
- for ( auto& it : rng_types_ )
+ vp_synced_rngs_.resize( kernel().vp_manager.get_num_threads() );
+ vp_specific_rngs_.resize( kernel().vp_manager.get_num_threads() );
+
+#pragma omp parallel
{
- delete it.second;
+ const auto tid = kernel().vp_manager.get_thread_id();
+ const std::uint32_t vp = kernel().vp_manager.get_vp(); // type required for rng initializer
+ vp_synced_rngs_[ tid ] = rng_types_[ current_rng_type_ ]->create( { base_seed_, THREAD_SYNCED_SEEDER_ } );
+ vp_specific_rngs_[ tid ] = rng_types_[ current_rng_type_ ]->create( { base_seed_, THREAD_SPECIFIC_SEEDER_, vp } );
}
-
- rng_types_.clear();
- vp_specific_rngs_.clear();
-}
-
-void
-nest::RandomManager::change_number_of_threads()
-{
- reset_rngs_();
}
void
-nest::RandomManager::reset_rngs_()
+nest::RandomManager::finalize( const bool reset_kernel )
{
- // Delete existing RNGs.
- delete rank_synced_rng_;
-
+ // Delete existing RNGs
auto delete_rngs = []( std::vector< RngPtr >& rng_vec )
{
for ( auto rng : rng_vec )
@@ -114,21 +108,19 @@ nest::RandomManager::reset_rngs_()
}
};
+ delete rank_synced_rng_;
delete_rngs( vp_synced_rngs_ );
delete_rngs( vp_specific_rngs_ );
+ vp_synced_rngs_.clear();
+ vp_specific_rngs_.clear();
- // Create new RNGs of the currently used RNG type.
- rank_synced_rng_ = rng_types_[ current_rng_type_ ]->create( { base_seed_, RANK_SYNCED_SEEDER_ } );
-
- vp_synced_rngs_.resize( kernel().vp_manager.get_num_threads() );
- vp_specific_rngs_.resize( kernel().vp_manager.get_num_threads() );
-
-#pragma omp parallel
+ if ( reset_kernel )
{
- const auto tid = kernel().vp_manager.get_thread_id();
- const std::uint32_t vp = kernel().vp_manager.get_vp();
- vp_synced_rngs_[ tid ] = rng_types_[ current_rng_type_ ]->create( { base_seed_, THREAD_SYNCED_SEEDER_ } );
- vp_specific_rngs_[ tid ] = rng_types_[ current_rng_type_ ]->create( { base_seed_, THREAD_SPECIFIC_SEEDER_, vp } );
+ for ( auto& it : rng_types_ )
+ {
+ delete it.second;
+ }
+ rng_types_.clear();
}
}
@@ -177,11 +169,10 @@ nest::RandomManager::set_status( const DictionaryDatum& d )
current_rng_type_ = rng_type;
}
- // If number of threads has been changed, we need to update the RNGs.
- bool n_threads_updated = d->known( names::local_num_threads );
- if ( n_threads_updated or rng_seed_updated or rng_type_updated )
+ if ( rng_seed_updated or rng_type_updated )
{
- reset_rngs_();
+ finalize( /* reset_kernel */ false );
+ initialize( /* reset_kernel */ false );
}
}
@@ -229,7 +220,7 @@ nest::RandomManager::check_rng_synchrony() const
template < typename RNG_TYPE >
void
-nest::RandomManager::register_rng_type( std::string name )
+nest::RandomManager::register_rng_type( const std::string& name )
{
rng_types_.insert( std::make_pair( name, new RandomGeneratorFactory< RNG_TYPE >() ) );
}
diff --git a/nestkernel/random_manager.h b/nestkernel/random_manager.h
index d69e379cb4..5956f54b0d 100644
--- a/nestkernel/random_manager.h
+++ b/nestkernel/random_manager.h
@@ -56,9 +56,8 @@ class RandomManager : public ManagerInterface
/**
* Register available RNG types, set default RNG type and create RNGs.
*/
- void initialize() override;
- void finalize() override;
- void change_number_of_threads() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
@@ -109,7 +108,7 @@ class RandomManager : public ManagerInterface
* @param RNG_TYPE Class fulfilling requirements of C++ RNG.
**/
template < typename RNG_TYPE >
- void register_rng_type( std::string name );
+ void register_rng_type( const std::string& name );
private:
/** Available RNG types. */
@@ -130,14 +129,6 @@ class RandomManager : public ManagerInterface
/** Random number generators specific to VPs. */
std::vector< RngPtr > vp_specific_rngs_;
- /**
- * Replace current RNGs with newly seeded generators.
- *
- * The new generators will be of type `current_rng_type_` and will be
- * seeded using `base_seed_`.
- **/
- void reset_rngs_();
-
/** RNG type used by default. */
static const std::string DEFAULT_RNG_TYPE_;
diff --git a/nestkernel/secondary_event.h b/nestkernel/secondary_event.h
index 1ba3800f06..3d5f339fd3 100644
--- a/nestkernel/secondary_event.h
+++ b/nestkernel/secondary_event.h
@@ -23,8 +23,10 @@
#ifndef SECONDARY_EVENT_H
#define SECONDARY_EVENT_H
-// c++ includes
-// C++ includes:
+// Includes from nestkernel
+#include "event.h"
+
+// C++ includes
#include
namespace nest
@@ -195,12 +197,7 @@ class DataSecondaryEvent : public SecondaryEvent
*
* See also:
*/
- void
- add_syn_id( const synindex synid ) override
- {
- VPManager::assert_single_threaded();
- supported_syn_ids_.insert( synid );
- }
+ void add_syn_id( const synindex synid ) override;
const std::set< synindex >&
get_supported_syn_ids() const override
@@ -221,12 +218,7 @@ class DataSecondaryEvent : public SecondaryEvent
supported_syn_ids_.clear();
}
- static void
- set_coeff_length( const size_t coeff_length )
- {
- VPManager::assert_single_threaded();
- coeff_length_ = coeff_length;
- }
+ static void set_coeff_length( const size_t coeff_length );
void
set_coeffarray( std::vector< DataType >& ca )
diff --git a/nestkernel/secondary_event_impl.h b/nestkernel/secondary_event_impl.h
new file mode 100644
index 0000000000..1ad6fe92ee
--- /dev/null
+++ b/nestkernel/secondary_event_impl.h
@@ -0,0 +1,51 @@
+/*
+ * 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 ae3ac6a689..c301344ba4 100644
--- a/nestkernel/simulation_manager.cpp
+++ b/nestkernel/simulation_manager.cpp
@@ -66,8 +66,13 @@ nest::SimulationManager::SimulationManager()
}
void
-nest::SimulationManager::initialize()
+nest::SimulationManager::initialize( const bool reset_kernel )
{
+ if ( not reset_kernel )
+ {
+ return;
+ }
+
Time::reset_to_defaults();
Time::reset_resolution();
@@ -101,7 +106,7 @@ nest::SimulationManager::initialize()
}
void
-nest::SimulationManager::finalize()
+nest::SimulationManager::finalize( const bool )
{
}
diff --git a/nestkernel/simulation_manager.h b/nestkernel/simulation_manager.h
index f93c761080..7b0b03e53e 100644
--- a/nestkernel/simulation_manager.h
+++ b/nestkernel/simulation_manager.h
@@ -49,8 +49,8 @@ class SimulationManager : public ManagerInterface
public:
SimulationManager();
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
diff --git a/nestkernel/source_table.cpp b/nestkernel/source_table.cpp
index 09c4195341..b5e7c49c73 100644
--- a/nestkernel/source_table.cpp
+++ b/nestkernel/source_table.cpp
@@ -54,9 +54,9 @@ nest::SourceTable::initialize()
#pragma omp parallel
{
const size_t tid = kernel().vp_manager.get_thread_id();
- sources_[ tid ].resize( 0 );
- resize_sources( tid );
- compressible_sources_[ tid ].resize( 0 );
+ sources_.at( tid ).resize( 0 );
+ resize_sources();
+ compressible_sources_.at( tid ).resize( 0 );
} // of omp parallel
}
@@ -266,9 +266,10 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t
}
void
-nest::SourceTable::resize_sources( const size_t tid )
+nest::SourceTable::resize_sources()
{
- sources_[ tid ].resize( kernel().model_manager.get_num_connection_models() );
+ kernel().vp_manager.assert_thread_parallel();
+ sources_.at( kernel().vp_manager.get_thread_id() ).resize( kernel().model_manager.get_num_connection_models() );
}
bool
diff --git a/nestkernel/source_table.h b/nestkernel/source_table.h
index 7247a75518..0ada191e85 100644
--- a/nestkernel/source_table.h
+++ b/nestkernel/source_table.h
@@ -332,10 +332,9 @@ class SourceTable
size_t num_unique_sources( const size_t tid, const synindex syn_id ) const;
/**
- * Resizes sources_ according to total number of threads and
- * synapse types.
+ * Resizes sources_ according to total number of threads and synapse types.
*/
- void resize_sources( const size_t tid );
+ void resize_sources();
/**
* Encodes combination of node ID and synapse types as single
diff --git a/nestkernel/sp_manager.cpp b/nestkernel/sp_manager.cpp
index d389cfaacc..345ac6b9c2 100644
--- a/nestkernel/sp_manager.cpp
+++ b/nestkernel/sp_manager.cpp
@@ -48,18 +48,22 @@ SPManager::SPManager()
SPManager::~SPManager()
{
- finalize();
}
void
-SPManager::initialize()
+SPManager::initialize( const bool reset_kernel )
{
+ if ( not reset_kernel )
+ {
+ return;
+ }
+
structural_plasticity_update_interval_ = 10000.;
structural_plasticity_enabled_ = false;
}
void
-SPManager::finalize()
+SPManager::finalize( const bool )
{
for ( std::vector< SPBuilder* >::const_iterator i = sp_conn_builders_.begin(); i != sp_conn_builders_.end(); i++ )
{
diff --git a/nestkernel/sp_manager.h b/nestkernel/sp_manager.h
index 86ea88a7af..79cc92a72a 100644
--- a/nestkernel/sp_manager.h
+++ b/nestkernel/sp_manager.h
@@ -60,8 +60,8 @@ class SPManager : public ManagerInterface
SPManager();
~SPManager() override;
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void get_status( DictionaryDatum& ) override;
/**
diff --git a/nestkernel/target_table_devices.cpp b/nestkernel/target_table_devices.cpp
index eebf678c37..da106e9b43 100644
--- a/nestkernel/target_table_devices.cpp
+++ b/nestkernel/target_table_devices.cpp
@@ -88,20 +88,19 @@ nest::TargetTableDevices::resize_to_number_of_neurons()
void
nest::TargetTableDevices::resize_to_number_of_synapse_types()
{
-#pragma omp parallel
+ kernel().vp_manager.assert_thread_parallel();
+
+ const size_t tid = kernel().vp_manager.get_thread_id();
+ for ( size_t lid = 0; lid < target_to_devices_.at( tid ).size(); ++lid )
{
- const size_t tid = kernel().vp_manager.get_thread_id();
- for ( size_t lid = 0; lid < target_to_devices_[ tid ].size(); ++lid )
- {
- // make sure this device has support for all synapse types
- target_to_devices_[ tid ][ lid ].resize( kernel().model_manager.get_num_connection_models(), nullptr );
- }
- for ( size_t ldid = 0; ldid < target_from_devices_[ tid ].size(); ++ldid )
- {
- // make sure this device has support for all synapse types
- target_from_devices_[ tid ][ ldid ].resize( kernel().model_manager.get_num_connection_models(), nullptr );
- }
- } // end omp parallel
+ // make sure this device has support for all synapse types
+ target_to_devices_.at( tid ).at( lid ).resize( kernel().model_manager.get_num_connection_models(), nullptr );
+ }
+ for ( size_t ldid = 0; ldid < target_from_devices_.at( tid ).size(); ++ldid )
+ {
+ // make sure this device has support for all synapse types
+ target_from_devices_.at( tid ).at( ldid ).resize( kernel().model_manager.get_num_connection_models(), nullptr );
+ }
}
void
diff --git a/nestkernel/vp_manager.cpp b/nestkernel/vp_manager.cpp
index 4f7d0d33e1..292f65239b 100644
--- a/nestkernel/vp_manager.cpp
+++ b/nestkernel/vp_manager.cpp
@@ -48,8 +48,13 @@ nest::VPManager::VPManager()
}
void
-nest::VPManager::initialize()
+nest::VPManager::initialize( const bool reset_kernel )
{
+ if ( not reset_kernel )
+ {
+ return;
+ }
+
// When the VPManager is initialized, you will have 1 thread again.
// Setting more threads will be done via nest::set_kernel_status
#ifdef _OPENMP
@@ -73,7 +78,7 @@ nest::VPManager::initialize()
}
void
-nest::VPManager::finalize()
+nest::VPManager::finalize( const bool )
{
}
@@ -188,11 +193,3 @@ nest::VPManager::set_num_threads( size_t n_threads )
omp_set_num_threads( n_threads_ );
#endif
}
-
-void
-nest::VPManager::assert_single_threaded()
-{
-#ifdef _OPENMP
- assert( omp_get_num_threads() == 1 );
-#endif
-}
diff --git a/nestkernel/vp_manager.h b/nestkernel/vp_manager.h
index b862d75cce..226c389adf 100644
--- a/nestkernel/vp_manager.h
+++ b/nestkernel/vp_manager.h
@@ -56,8 +56,8 @@ class VPManager : public ManagerInterface
{
}
- void initialize() override;
- void finalize() override;
+ void initialize( const bool ) override;
+ void finalize( const bool ) override;
void set_status( const DictionaryDatum& ) override;
void get_status( DictionaryDatum& ) override;
@@ -144,7 +144,12 @@ class VPManager : public ManagerInterface
/**
* Fails if NEST is in thread-parallel section.
*/
- static void assert_single_threaded();
+ void assert_single_threaded() const;
+
+ /**
+ * Fails if NEST is not in thread-parallel section.
+ */
+ void assert_thread_parallel() const;
/**
* Returns the number of processes that are taken care of by a single thread
@@ -186,4 +191,21 @@ nest::VPManager::get_num_threads() const
return n_threads_;
}
+inline void
+nest::VPManager::assert_single_threaded() const
+{
+#ifdef _OPENMP
+ assert( omp_get_num_threads() == 1 );
+#endif
+}
+
+inline void
+nest::VPManager::assert_thread_parallel() const
+{
+#ifdef _OPENMP
+ assert( omp_get_num_threads() == n_threads_ );
+#endif
+}
+
+
#endif /* #ifndef VP_MANAGER_H */
diff --git a/testsuite/regressiontests/ticket-478.sli b/testsuite/regressiontests/ticket-478.sli
index e8c1a247a5..8a76febcc5 100644
--- a/testsuite/regressiontests/ticket-478.sli
+++ b/testsuite/regressiontests/ticket-478.sli
@@ -44,8 +44,9 @@ Author: Hans Ekkehard Plesser, 2010-10-22
M_ERROR setverbosity
-% Gap junctions not relevant for spiking devices as senders
-/excluded_synapses [ /gap_junction ] def
+% Gap junctions and sic_connections not relevant for spiking devices as senders
+/excluded_synapses [ /gap_junction /sic_connection /rate_connection_delayed
+ /rate_connection_instantaneous ] def
% find all static and plastic synapses
% we identify as static all synapses that have the same default parameter names