From 01321446dd308f260c0d4e8057daa5992dd1694f Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 12:11:08 +0100 Subject: [PATCH 01/10] extend test suite to run more tests also in pre-commit --- .mypy.ini | 10 - .pre-commit-config.yaml | 78 +++- .pylintrc | 2 +- bin/nest-server-mpi | 96 ++--- doc/htmldoc/_ext/extract_api_functions.py | 6 +- libnestutil/block_vector.h | 4 +- libnestutil/sort.h | 12 +- models/aeif_cond_alpha_multisynapse.cpp | 4 +- models/aeif_cond_beta_multisynapse.cpp | 4 +- models/cm_tree.cpp | 4 +- models/gif_pop_psc_exp.cpp | 2 +- models/glif_cond.cpp | 6 +- models/poisson_generator_ps.cpp | 4 +- models/pp_psc_delta.cpp | 2 +- nestkernel/archiving_node.cpp | 4 +- nestkernel/conn_builder.cpp | 384 +++++++++--------- nestkernel/conn_builder.h | 4 +- nestkernel/connection_creator.cpp | 112 +++-- nestkernel/connection_creator_impl.h | 8 +- nestkernel/connection_manager.cpp | 10 +- nestkernel/eprop_archiving_node_impl.h | 4 +- nestkernel/event_delivery_manager.cpp | 4 +- nestkernel/kernel_manager.cpp | 218 +++++++++- nestkernel/layer_impl.h | 10 +- nestkernel/music_manager.cpp | 16 +- nestkernel/nest_time.h | 6 +- nestkernel/nestmodule.cpp | 8 +- nestkernel/node_collection.cpp | 2 +- nestkernel/node_manager.cpp | 4 +- nestkernel/parameter.h | 2 +- nestkernel/position.h | 3 +- nestkernel/ring_buffer_impl.h | 2 +- nestkernel/simulation_manager.cpp | 16 +- nestkernel/sonata_connector.cpp | 2 +- nestkernel/source_table.cpp | 18 +- nestkernel/source_table.h | 4 +- nestkernel/spatial.cpp | 268 ++++++++---- nestkernel/stopwatch_impl.h | 10 +- nestkernel/structural_plasticity_node.cpp | 111 +++-- nestkernel/target_table.cpp | 4 +- nestkernel/target_table_devices.cpp | 4 +- nestkernel/target_table_devices.h | 4 +- nestkernel/target_table_devices_impl.h | 4 +- pyproject.toml | 38 ++ requirements_testing.txt | 1 + sli/booldatum.cc | 6 +- sli/token.cc | 15 +- .../mpi/{2 => nproc2}/connect_test_base.py | 0 .../{2 => nproc2}/test_connect_all_to_all.py | 0 .../{2 => nproc2}/test_connect_arrays_mpi.py | 0 .../test_connect_fixed_indegree.py | 0 .../test_connect_fixed_outdegree.py | 0 .../test_connect_fixed_total_number.py | 0 .../{2 => nproc2}/test_connect_one_to_one.py | 0 .../test_connect_pairwise_bernoulli.py | 0 ...st_connect_symmetric_pairwise_bernoulli.py | 0 .../mpi/{2 => nproc2}/test_getnodes.py | 0 .../mpi/{2 => nproc2}/test_issue_1974.py | 0 .../mpi/{2 => nproc2}/test_issue_3099.py | 0 .../mpi/{2 => nproc2}/test_issue_3108.py | 0 .../mpi/{2 => nproc2}/test_issue_576.py | 0 .../mpi/{2 => nproc2}/test_multiplicity.py | 0 .../mpi/{2 => nproc2}/test_neuron_vp.py | 0 .../{2 => nproc2}/test_spatial_positions.py | 0 .../test_synapsecollection_mpi.py | 0 .../mpi/{3 => nproc3}/test_issue_3108.py | 0 .../mpi/{3 => nproc3}/test_neuron_vp.py | 0 .../test_consistent_local_vps.py | 0 .../mpi/{4 => nproc4}/test_delay_exchange.py | 0 .../mpi/{4 => nproc4}/test_getnodes.py | 0 .../mpi/{4 => nproc4}/test_issue_1974.py | 0 .../mpi/{4 => nproc4}/test_issue_3108.py | 0 .../mpi/{4 => nproc4}/test_localonly.py | 0 .../test_set_status_resolution_nthreads.py | 0 .../{4 => nproc4}/test_spatial_positions.py | 0 .../test_spike_train_injector_mpi.py | 0 .../sli2py_regressions/test_ticket_638.py | 2 +- .../sli2py_regressions/test_ticket_673.py | 2 +- testsuite/pytests/test_connect_all_to_all.py | 3 +- .../pytests/test_connect_fixed_indegree.py | 3 +- .../pytests/test_connect_fixed_outdegree.py | 3 +- .../test_connect_fixed_total_number.py | 3 +- testsuite/pytests/test_connect_one_to_one.py | 3 +- .../test_connect_pairwise_bernoulli.py | 3 +- .../pytests/test_connect_pairwise_poisson.py | 3 +- ...st_connect_symmetric_pairwise_bernoulli.py | 3 +- testsuite/regressiontests/issue-1703.py | 4 +- .../sli2py_ignore/issue-779-1016.py | 4 +- testsuite/run_test.sh | 4 +- testsuite/summarize_tests.py | 6 +- 90 files changed, 993 insertions(+), 593 deletions(-) delete mode 100644 .mypy.ini rename testsuite/pytests/mpi/{2 => nproc2}/connect_test_base.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_all_to_all.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_arrays_mpi.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_fixed_indegree.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_fixed_outdegree.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_fixed_total_number.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_one_to_one.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_pairwise_bernoulli.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_connect_symmetric_pairwise_bernoulli.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_getnodes.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_issue_1974.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_issue_3099.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_issue_3108.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_issue_576.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_multiplicity.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_neuron_vp.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_spatial_positions.py (100%) rename testsuite/pytests/mpi/{2 => nproc2}/test_synapsecollection_mpi.py (100%) rename testsuite/pytests/mpi/{3 => nproc3}/test_issue_3108.py (100%) rename testsuite/pytests/mpi/{3 => nproc3}/test_neuron_vp.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_consistent_local_vps.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_delay_exchange.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_getnodes.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_issue_1974.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_issue_3108.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_localonly.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_set_status_resolution_nthreads.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_spatial_positions.py (100%) rename testsuite/pytests/mpi/{4 => nproc4}/test_spike_train_injector_mpi.py (100%) diff --git a/.mypy.ini b/.mypy.ini deleted file mode 100644 index b04439f171..0000000000 --- a/.mypy.ini +++ /dev/null @@ -1,10 +0,0 @@ -# For configuation details see -# - -[mypy] -exclude = .git/, .snakemake/, .pytest_cache/, sync-test-env/, conda/, env/ -explicit_package_bases = True - -# Check explanations of error codes -# https://mypy.readthedocs.io/en/stable/error_code_list.html -disable_error_code = attr-defined, index, import, call-arg, misc, dict-item, arg-type, operator, call-overload, assignment, list-item, var-annotated, valid-type diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f0b9728371..830185d3b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,8 @@ +fail_fast: true + repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace @@ -10,24 +12,34 @@ repos: - id: fix-byte-order-marker - repo: https://github.com/gitleaks/gitleaks - rev: v8.16.3 + rev: v8.10.0 hooks: - id: gitleaks - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 7.0.0 hooks: - id: isort args: ["--profile", "black", "--thirdparty", "nest"] - repo: https://github.com/psf/black - rev: 23.7.0 + rev: 25.11.0 hooks: - id: black language_version: python3 + - repo: https://github.com/PyCQA/flake8 + rev: 7.3.0 + hooks: + - id: flake8 + + - repo: https://github.com/PyCQA/pydocstyle + rev: 6.3.0 + hooks: + - id: pydocstyle + - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.10.0.1 + rev: v0.11.0.1 hooks: - id: shellcheck # explicitly add input files that are not "*.sh" @@ -35,18 +47,60 @@ repos: # # note that these differ from arguments in .github/workflows/nestbuildmatrix.yml # IF YOU READ THIS: recheck for consistency with `find . -iname "*.sh" -o -iname "*.sh.in"` - "bin/nest_vars.sh.in", # testsuite/do_tests.sh:112 requires this for `. "${PREFIX}/bin/nest_vars.sh"` - "testsuite/run_test.sh", - "testsuite/do_tests.sh", - "testsuite/junit_xml.sh", - "examples/run_examples.sh", - "examples/list_examples.sh", + "./testsuite/junit_xml.sh", + "./testsuite/do_tests.sh", + "./testsuite/run_test.sh", + "./bin/nest_vars.sh.in", # testsuite/do_tests.sh:112 requires this for `. "${PREFIX}/bin/nest_vars.sh"` + "./cmake/CheckFiles/check_return_val.sh", + "./examples/run_examples.sh", + "./examples/list_examples.sh", + "./build_support/version_info.sh", + "./build_support/install_csa-libneurosim.sh", + "./build_support/install_music.sh", + "./build_support/check_forbidden_types.sh", + "./build_support/format_all_c_c++_files.sh", + "./build_support/install_sionlib.sh", ] - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.4 + rev: v21.1.7 hooks: - id: clang-format types_or: [c++] + # ref https://pylint.pycqa.org/en/latest/user_guide/installation/pre-commit-integration.html + - repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + require_serial: true + types: ["python"] + args: + - "-rn" # Only display messages + - "-sn" # Don't display the score + - "--rcfile=.pylintrc" # Link to your config file + - "--load-plugins=pylint.extensions.docparams" # Load an extension + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.19.0 + hooks: + - id: mypy + additional_dependencies: + - 'jinja2' + - 'python-dateutil' + - 'pytest' + - 'semver' + - 'types-python-dateutil' + - 'types-requests' + - 'matplotlib-stubs' + - 'pandas-stubs' + args: + - --show-error-codes + - --config-file + - pyproject.toml + - . + pass_filenames: false + exclude: 'build/.*|thirdparty/.*' diff --git a/.pylintrc b/.pylintrc index 9569543737..43ab16a8a1 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,7 +6,7 @@ options = unneeded-not, line-too-long, unnecessary-semicolon, trailing-whitespace, missing-final-newline, bad-indentation, multiple-statements, bare-except ignore = CVS .git conda env __pycache__ .pytest_cache .mypy_cache -disable = no-member, redefined-outer-name, invalid-name, consider-using-f-string, wrong-import-order, missing-function-docstring, missing-method-docstring, missing-class-docstring, attribute-defined-outside-init, no-else-return, cell-var-from-loop, import-error, pointless-string-statement, unused-import, redefined-builtin, superfluous-parens, unused-variable, too-many-locals, consider-using-from-import, consider-using-enumerate, no-name-in-module, too-many-arguments, too-many-instance-attributes, import-outside-toplevel, too-few-public-methods, cyclic-import, missing-module-docstring, unidiomatic-typecheck, dangerous-default-value, unused-argument, use-dict-literal, exec-used, no-self-use, too-many-statements, ungrouped-imports, consider-using-sys-exit, too-many-statements, redundant-u-string-prefix, protected-access, consider-using-dict-comprehension, no-else-raise, too-many-nested-blocks, use-a-generator, reimported, undefined-variable, too-many-branches, raise-missing-from, trailing-comma-tuple, unspecified-encoding, consider-using-with, f-string-without-interpolation, broad-except, unnecessary-pass, global-statement, too-many-lines, consider-merging-isinstance, redefined-argument-from-local, global-variable-undefined, use-implicit-booleaness-not-len, inconsistent-return-statements, consider-using-in, inconsistent-return-statements, keyword-arg-before-vararg, consider-using-dict-items, import-self, fixme, c-extension-no-member, too-many-public-methods, consider-iterating-dictionary, consider-using-max-builtin, super-with-arguments, expression-not-assigned, unnecessary-comprehension, no-self-argument, chained-comparison, undefined-loop-variable, empty-docstring, use-maxsplit-arg, pointless-statement, wrong-import-position, redundant-unittest-assert, eval-used, not-callable, invalid-unary-operand-type, consider-using-generator, R0801, unnecessary-dunder-call, logging-fstring-interpolation, consider-using-get, useless-object-inheritance, unrecognized-option, unknown-option-value, useless-option-value +disable = no-member, redefined-outer-name, invalid-name, consider-using-f-string, wrong-import-order, missing-function-docstring, missing-method-docstring, missing-class-docstring, attribute-defined-outside-init, no-else-return, cell-var-from-loop, import-error, pointless-string-statement, unused-import, redefined-builtin, superfluous-parens, unused-variable, too-many-locals, consider-using-from-import, consider-using-enumerate, no-name-in-module, too-many-arguments, too-many-instance-attributes, too-many-return-statements, import-outside-toplevel, too-few-public-methods, cyclic-import, missing-module-docstring, unidiomatic-typecheck, dangerous-default-value, unused-argument, use-dict-literal, exec-used, no-self-use, too-many-statements, ungrouped-imports, consider-using-sys-exit, too-many-statements, redundant-u-string-prefix, protected-access, consider-using-dict-comprehension, no-else-raise, too-many-nested-blocks, use-a-generator, reimported, undefined-variable, too-many-branches, raise-missing-from, trailing-comma-tuple, unspecified-encoding, consider-using-with, f-string-without-interpolation, broad-except, unnecessary-pass, global-statement, too-many-lines, consider-merging-isinstance, redefined-argument-from-local, global-variable-undefined, use-implicit-booleaness-not-len, inconsistent-return-statements, consider-using-in, inconsistent-return-statements, keyword-arg-before-vararg, consider-using-dict-items, import-self, fixme, c-extension-no-member, too-many-public-methods, consider-iterating-dictionary, consider-using-max-builtin, super-with-arguments, expression-not-assigned, unnecessary-comprehension, no-self-argument, chained-comparison, undefined-loop-variable, empty-docstring, use-maxsplit-arg, pointless-statement, wrong-import-position, redundant-unittest-assert, eval-used, not-callable, invalid-unary-operand-type, consider-using-generator, R0801, unnecessary-dunder-call, logging-fstring-interpolation, consider-using-get, useless-object-inheritance, unrecognized-option, unknown-option-value, useless-option-value, missing-type-doc, too-many-positional-arguments, missing-param-doc, logging-not-lazy, useless-return, duplicate-key, possibly-used-before-assignment, unnecessary-lambda, consider-using-min-builtin, using-constant-test, unexpected-keyword-arg const-naming-style = snake_case method-naming-style = PascalCase diff --git a/bin/nest-server-mpi b/bin/nest-server-mpi index 3af45073c7..fde56b6cfd 100755 --- a/bin/nest-server-mpi +++ b/bin/nest-server-mpi @@ -13,21 +13,17 @@ Options: """ -from docopt import docopt -from mpi4py import MPI - -if __name__ == "__main__": - opt = docopt(__doc__) - import logging import os import time -logger = logging.getLogger(__name__) -logger.setLevel(os.getenv("NEST_SERVER_MPI_LOGGER_LEVEL", "INFO")) - import nest import nest.server +from docopt import docopt +from mpi4py import MPI + +logger = logging.getLogger(__name__) +logger.setLevel(os.getenv("NEST_SERVER_MPI_LOGGER_LEVEL", "INFO")) HOST = os.getenv("NEST_SERVER_HOST", "127.0.0.1") PORT = os.getenv("NEST_SERVER_PORT", "52425") @@ -41,41 +37,47 @@ def log(call_name, msg): logger.debug(msg) -if rank == 0: - logger.info("==> Starting NEST Server Master on rank 0") - nest.server.set_mpi_comm(comm) - nest.server.run_mpi_app(host=opt.get("--host", HOST), port=opt.get("--port", PORT)) - -else: - logger.info(f"==> Starting NEST Server Worker on rank {rank}") - nest.server.set_mpi_comm(comm) - - while True: - log("spinwait", "waiting for call bcast") - call_name = comm.bcast(None, root=0) - - log(call_name, "received call bcast, waiting for data bcast") - data = comm.bcast(None, root=0) - - log(call_name, f"received data bcast, data={data}") - args, kwargs = data - - if call_name == "exec": - response = nest.server.do_exec(args, kwargs) - else: - call, args, kwargs = nest.server.nestify(call_name, args, kwargs) - log(call_name, f"local call, args={args}, kwargs={kwargs}") - - # The following exception handler is useful if an error - # occurs simulataneously on all processes. If only a - # subset of processes raises an exception, a deadlock due - # to mismatching MPI communication calls is inevitable on - # the next call. - try: - response = call(*args, **kwargs) - except Exception: - logger.error("Failed to execute call") - continue - - log(call_name, f"sending reponse gather, data={response}") - comm.gather(nest.serialize_data(response), root=0) +def main(): + opt = docopt(__doc__) + if rank == 0: + logger.info("==> Starting NEST Server Master on rank 0") + nest.server.set_mpi_comm(comm) + nest.server.run_mpi_app(host=opt.get("--host", HOST), port=opt.get("--port", PORT)) + + else: + logger.info(f"==> Starting NEST Server Worker on rank {rank}") + nest.server.set_mpi_comm(comm) + + while True: + log("spinwait", "waiting for call bcast") + call_name = comm.bcast(None, root=0) + + log(call_name, "received call bcast, waiting for data bcast") + data = comm.bcast(None, root=0) + + log(call_name, f"received data bcast, data={data}") + args, kwargs = data + + if call_name == "exec": + response = nest.server.do_exec(args, kwargs) + else: + call, args, kwargs = nest.server.nestify(call_name, args, kwargs) + log(call_name, f"local call, args={args}, kwargs={kwargs}") + + # The following exception handler is useful if an error + # occurs simulataneously on all processes. If only a + # subset of processes raises an exception, a deadlock due + # to mismatching MPI communication calls is inevitable on + # the next call. + try: + response = call(*args, **kwargs) + except Exception: + logger.error("Failed to execute call") + continue + + log(call_name, f"sending reponse gather, data={response}") + comm.gather(nest.serialize_data(response), root=0) + + +if __name__ == "__main__": + main() diff --git a/doc/htmldoc/_ext/extract_api_functions.py b/doc/htmldoc/_ext/extract_api_functions.py index 09b0f2e36f..29c81be651 100644 --- a/doc/htmldoc/_ext/extract_api_functions.py +++ b/doc/htmldoc/_ext/extract_api_functions.py @@ -35,9 +35,9 @@ def find_all_variables(file_path): """ - This function gets the names of all functions listed in ``__all__`` - in each of the PyNEST API files, along with the Kernel Attributes - found in ``__init__.py`` of ``pynest/nest/``. + Gets the names of all functions listed in ``__all__`` in each of the PyNEST + API files, along with the Kernel Attributes found in ``__init__.py`` of + ``pynest/nest/``. """ all_variables = None diff --git a/libnestutil/block_vector.h b/libnestutil/block_vector.h index 5648804bac..278977dda8 100644 --- a/libnestutil/block_vector.h +++ b/libnestutil/block_vector.h @@ -323,7 +323,7 @@ class BlockVector template < typename value_type_ > BlockVector< value_type_ >::BlockVector() : blockmap_( - std::vector< std::vector< value_type_ > >( 1, std::move( std::vector< value_type_ >( max_block_size ) ) ) ) + std::vector< std::vector< value_type_ > >( 1, std::move( std::vector< value_type_ >( max_block_size ) ) ) ) , finish_( begin() ) { } @@ -331,7 +331,7 @@ BlockVector< value_type_ >::BlockVector() template < typename value_type_ > BlockVector< value_type_ >::BlockVector( size_t n ) : blockmap_( - std::vector< std::vector< value_type_ > >( 1, std::move( std::vector< value_type_ >( max_block_size ) ) ) ) + std::vector< std::vector< value_type_ > >( 1, std::move( std::vector< value_type_ >( max_block_size ) ) ) ) , finish_( begin() ) { size_t num_blocks_needed = std::ceil( static_cast< double >( n ) / max_block_size ); diff --git a/libnestutil/sort.h b/libnestutil/sort.h index 4712cde804..6071cab267 100644 --- a/libnestutil/sort.h +++ b/libnestutil/sort.h @@ -49,12 +49,12 @@ template < typename T > inline size_t median3_( const BlockVector< T >& vec, const size_t i, const size_t j, const size_t k ) { - return ( ( vec[ i ] < vec[ j ] ) ? ( ( vec[ j ] < vec[ k ] ) ? j - : ( vec[ i ] < vec[ k ] ) ? k - : i ) - : ( ( vec[ k ] < vec[ j ] ) ? j - : ( vec[ k ] < vec[ i ] ) ? k - : i ) ); + return ( ( vec[ i ] < vec[ j ] ) ? ( ( vec[ j ] < vec[ k ] ) ? j + : ( vec[ i ] < vec[ k ] ) ? k + : i ) + : ( ( vec[ k ] < vec[ j ] ) ? j + : ( vec[ k ] < vec[ i ] ) ? k + : i ) ); } /** diff --git a/models/aeif_cond_alpha_multisynapse.cpp b/models/aeif_cond_alpha_multisynapse.cpp index f027713973..b4c4b97b9a 100644 --- a/models/aeif_cond_alpha_multisynapse.cpp +++ b/models/aeif_cond_alpha_multisynapse.cpp @@ -321,8 +321,8 @@ aeif_cond_alpha_multisynapse::State_::get( DictionaryDatum& d ) const std::vector< double >* g = new std::vector< double >(); for ( size_t i = 0; - i < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUM_STATE_ELEMENTS_PER_RECEPTOR ); - ++i ) + i < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUM_STATE_ELEMENTS_PER_RECEPTOR ); + ++i ) { dg->push_back( y_[ State_::DG + ( State_::NUM_STATE_ELEMENTS_PER_RECEPTOR * i ) ] ); g->push_back( y_[ State_::G + ( State_::NUM_STATE_ELEMENTS_PER_RECEPTOR * i ) ] ); diff --git a/models/aeif_cond_beta_multisynapse.cpp b/models/aeif_cond_beta_multisynapse.cpp index 5ef7e10717..a25a26705f 100644 --- a/models/aeif_cond_beta_multisynapse.cpp +++ b/models/aeif_cond_beta_multisynapse.cpp @@ -329,8 +329,8 @@ aeif_cond_beta_multisynapse::State_::get( DictionaryDatum& d ) const std::vector< double >* g = new std::vector< double >(); for ( size_t i = 0; - i < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUM_STATE_ELEMENTS_PER_RECEPTOR ); - ++i ) + i < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUM_STATE_ELEMENTS_PER_RECEPTOR ); + ++i ) { dg->push_back( y_[ State_::DG + ( State_::NUM_STATE_ELEMENTS_PER_RECEPTOR * i ) ] ); g->push_back( y_[ State_::G + ( State_::NUM_STATE_ELEMENTS_PER_RECEPTOR * i ) ] ); diff --git a/models/cm_tree.cpp b/models/cm_tree.cpp index 52121ca2fe..5cc134ff84 100644 --- a/models/cm_tree.cpp +++ b/models/cm_tree.cpp @@ -290,7 +290,7 @@ void nest::CompTree::set_parents() { for ( auto compartment_idx_it = compartment_indices_.begin(); compartment_idx_it != compartment_indices_.end(); - ++compartment_idx_it ) + ++compartment_idx_it ) { Compartment* comp_ptr = get_compartment( *compartment_idx_it ); // will be nullptr if root @@ -309,7 +309,7 @@ nest::CompTree::set_compartments() compartments_.clear(); for ( auto compartment_idx_it = compartment_indices_.begin(); compartment_idx_it != compartment_indices_.end(); - ++compartment_idx_it ) + ++compartment_idx_it ) { compartments_.push_back( get_compartment( *compartment_idx_it ) ); } diff --git a/models/gif_pop_psc_exp.cpp b/models/gif_pop_psc_exp.cpp index 43299c877f..aed27e072a 100644 --- a/models/gif_pop_psc_exp.cpp +++ b/models/gif_pop_psc_exp.cpp @@ -592,7 +592,7 @@ nest::gif_pop_psc_exp::update( Time const& origin, const long from, const long t const double ompl = ( 1. - P_lambda_ ); V_.v_[ k ] = ompl * ompl * V_.v_[ k ] + P_lambda_ * V_.m_[ k ]; V_.m_[ k ] = ompl * V_.m_[ k ]; // line 26 of [1] - } // line 27 of [1] + } // line 27 of [1] double P_Lambda_; if ( ( Z_ + V_.z_ ) > 0.0 ) diff --git a/models/glif_cond.cpp b/models/glif_cond.cpp index a1434786b9..bf943c2551 100644 --- a/models/glif_cond.cpp +++ b/models/glif_cond.cpp @@ -405,9 +405,9 @@ nest::glif_cond::State_::get( DictionaryDatum& d, const Parameters_& p ) const std::vector< double >* dg = new std::vector< double >(); std::vector< double >* g = new std::vector< double >(); - for ( size_t i = 0; i - < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUMBER_OF_STATES_ELEMENTS_PER_RECEPTOR ); - ++i ) + for ( size_t i = 0; + i < ( ( y_.size() - State_::NUMBER_OF_FIXED_STATES_ELEMENTS ) / State_::NUMBER_OF_STATES_ELEMENTS_PER_RECEPTOR ); + ++i ) { dg->push_back( y_[ State_::DG_SYN - State_::NUMBER_OF_RECORDABLES_ELEMENTS + ( i * State_::NUMBER_OF_STATES_ELEMENTS_PER_RECEPTOR ) ] ); diff --git a/models/poisson_generator_ps.cpp b/models/poisson_generator_ps.cpp index 7a913d15bc..c6b71fd3e7 100644 --- a/models/poisson_generator_ps.cpp +++ b/models/poisson_generator_ps.cpp @@ -155,8 +155,8 @@ nest::poisson_generator_ps::pre_run_hook() Time min_time = B_.next_spike_.begin()->first; for ( std::vector< Buffers_::SpikeTime >::const_iterator it = B_.next_spike_.begin() + 1; - it != B_.next_spike_.end(); - ++it ) + it != B_.next_spike_.end(); + ++it ) { min_time = std::min( min_time, it->first ); } diff --git a/models/pp_psc_delta.cpp b/models/pp_psc_delta.cpp index 482fde1dff..44fa53144f 100644 --- a/models/pp_psc_delta.cpp +++ b/models/pp_psc_delta.cpp @@ -447,7 +447,7 @@ nest::pp_psc_delta::update( Time const& origin, const long from, const long to ) S_.y3_ = 0.0; } } // S_.y3_ = P_.V_reset_; - } // if (rate > 0.0) + } // if (rate > 0.0) } else // Neuron is within dead time { diff --git a/nestkernel/archiving_node.cpp b/nestkernel/archiving_node.cpp index 7ad511eb3c..087fe7efff 100644 --- a/nestkernel/archiving_node.cpp +++ b/nestkernel/archiving_node.cpp @@ -71,8 +71,8 @@ ArchivingNode::register_stdp_connection( double t_first_read, double delay ) // For details see bug #218. MH 08-04-22 for ( std::deque< histentry >::iterator runner = history_.begin(); - runner != history_.end() and ( t_first_read - runner->t_ > -1.0 * kernel().connection_manager.get_stdp_eps() ); - ++runner ) + runner != history_.end() and ( t_first_read - runner->t_ > -1.0 * kernel().connection_manager.get_stdp_eps() ); + ++runner ) { ( runner->access_counter_ )++; } diff --git a/nestkernel/conn_builder.cpp b/nestkernel/conn_builder.cpp index f70f00f0b4..380e1f323f 100644 --- a/nestkernel/conn_builder.cpp +++ b/nestkernel/conn_builder.cpp @@ -35,11 +35,6 @@ #include "node.h" #include "vp_manager_impl.h" -// Includes from sli: -#include "dict.h" -#include "fdstream.h" -#include "name.h" - // Includes from C++: #include @@ -47,8 +42,8 @@ nest::ConnBuilder::ConnBuilder( const std::string& primary_rule, NodeCollectionPTR sources, NodeCollectionPTR targets, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : third_in_builder_( nullptr ) , third_out_builder_( nullptr ) , primary_builder_( kernel().connection_manager.get_conn_builder( primary_rule, @@ -65,26 +60,26 @@ nest::ConnBuilder::ConnBuilder( const std::string& primary_rule, NodeCollectionPTR sources, NodeCollectionPTR targets, NodeCollectionPTR third, - const DictionaryDatum& conn_spec, - const DictionaryDatum& third_conn_spec, - const std::map< Name, std::vector< DictionaryDatum > >& syn_specs ) + const Dictionary& conn_spec, + const Dictionary& third_conn_spec, + const std::map< std::string, std::vector< Dictionary > >& syn_specs ) : third_in_builder_( new ThirdInBuilder( sources, - third, - third_conn_spec, - const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::third_in ] ) ) + third, + third_conn_spec, + const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::third_in ] ) ) , third_out_builder_( kernel().connection_manager.get_third_conn_builder( third_rule, third, targets, third_in_builder_, third_conn_spec, // const_cast here seems required, clang complains otherwise; try to clean up when Datums disappear - const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::third_out ] ) ) + const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::third_out ] ) ) , primary_builder_( kernel().connection_manager.get_conn_builder( primary_rule, sources, targets, third_out_builder_, conn_spec, - const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::primary ] ) ) + const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::primary ] ) ) { } @@ -119,8 +114,8 @@ nest::ConnBuilder::disconnect() nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : sources_( sources ) , targets_( targets ) , third_out_( third_out ) @@ -136,9 +131,9 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, // We only read a subset of rule-related parameters here. The property 'rule' // has already been taken care of in ConnectionManager::get_conn_builder() and // rule-specific parameters are handled by the subclass constructors. - updateValue< bool >( conn_spec, names::allow_autapses, allow_autapses_ ); - updateValue< bool >( conn_spec, names::allow_multapses, allow_multapses_ ); - updateValue< bool >( conn_spec, names::make_symmetric, make_symmetric_ ); + conn_spec.update_value< bool >( names::allow_autapses, allow_autapses_ ); + conn_spec.update_value< bool >( names::allow_multapses, allow_multapses_ ); + conn_spec.update_value< bool >( names::make_symmetric, make_symmetric_ ); if ( make_symmetric_ and third_out_ ) { @@ -157,22 +152,21 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, delays_.resize( syn_specs.size() ); synapse_params_.resize( syn_specs.size() ); synapse_model_id_.resize( syn_specs.size() ); - synapse_model_id_[ 0 ] = kernel().model_manager.get_synapse_model_id( "static_synapse" ); param_dicts_.resize( syn_specs.size() ); // loop through vector of synapse dictionaries, and set synapse parameters for ( size_t synapse_indx = 0; synapse_indx < syn_specs.size(); ++synapse_indx ) { - auto syn_params = syn_specs[ synapse_indx ]; + auto& syn_params = syn_specs[ synapse_indx ]; set_synapse_model_( syn_params, synapse_indx ); set_default_weight_or_delay_( syn_params, synapse_indx ); - DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); + Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); #ifdef HAVE_MUSIC // We allow music_channel as alias for receptor_type during connection setup - ( *syn_defaults )[ names::music_channel ] = 0; + syn_defaults[ names::music_channel ] = 0; #endif set_synapse_params( syn_defaults, syn_params, synapse_indx ); @@ -326,11 +320,11 @@ nest::BipartiteConnBuilder::connect() } } // check if any exceptions have been raised - for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) + for ( auto eptr : exceptions_raised_ ) { - if ( exceptions_raised_.at( tid ).get() ) + if ( eptr ) { - throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); + std::rethrow_exception( eptr ); } } } @@ -348,11 +342,11 @@ nest::BipartiteConnBuilder::disconnect() } // check if any exceptions have been raised - for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) + for ( auto eptr : exceptions_raised_ ) { - if ( exceptions_raised_.at( tid ).get() ) + if ( eptr ) { - throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); + std::rethrow_exception( eptr ); } } } @@ -370,17 +364,13 @@ nest::BipartiteConnBuilder::update_param_dict_( size_t snode_id, { if ( synapse_parameter.second->provides_long() ) { - // change value of dictionary entry without allocating new datum - IntegerDatum* id = static_cast< IntegerDatum* >( - ( ( *param_dicts_[ synapse_indx ][ target_thread ] )[ synapse_parameter.first ] ).datum() ); - ( *id ) = synapse_parameter.second->value_int( target_thread, rng, snode_id, &target ); + param_dicts_[ synapse_indx ][ target_thread ][ synapse_parameter.first ] = + synapse_parameter.second->value_int( target_thread, rng, snode_id, &target ); } else { - // change value of dictionary entry without allocating new datum - DoubleDatum* dd = static_cast< DoubleDatum* >( - ( ( *param_dicts_[ synapse_indx ][ target_thread ] )[ synapse_parameter.first ] ).datum() ); - ( *dd ) = synapse_parameter.second->value_double( target_thread, rng, snode_id, &target ); + param_dicts_[ synapse_indx ][ target_thread ][ synapse_parameter.first ] = + synapse_parameter.second->value_double( target_thread, rng, snode_id, &target ); } } } @@ -499,13 +489,11 @@ nest::BipartiteConnBuilder::loop_over_targets_() const } void -nest::BipartiteConnBuilder::set_synapse_model_( DictionaryDatum syn_params, size_t synapse_indx ) +nest::BipartiteConnBuilder::set_synapse_model_( const Dictionary& syn_params, size_t synapse_indx ) { - if ( not syn_params->known( names::synapse_model ) ) - { - throw BadProperty( "Synapse spec must contain synapse model." ); - } - const std::string syn_name = ( *syn_params )[ names::synapse_model ]; + const std::string syn_name = syn_params.known( names::synapse_model ) + ? syn_params.get< std::string >( names::synapse_model ) + : std::string( "static_synapse" ); // The following call will throw "UnknownSynapseType" if syn_name is not naming a known model const size_t synapse_model_id = kernel().model_manager.get_synapse_model_id( syn_name ); @@ -517,15 +505,14 @@ nest::BipartiteConnBuilder::set_synapse_model_( DictionaryDatum syn_params, size } void -nest::BipartiteConnBuilder::set_default_weight_or_delay_( DictionaryDatum syn_params, size_t synapse_indx ) +nest::BipartiteConnBuilder::set_default_weight_or_delay_( const Dictionary& syn_params, size_t synapse_indx ) { - DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); + Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); // All synapse models have the possibility to set the delay (see SynIdDelay), but some have // homogeneous weights, hence it should be possible to set the delay without the weight. - default_weight_[ synapse_indx ] = not syn_params->known( names::weight ); - - default_delay_[ synapse_indx ] = not syn_params->known( names::delay ); + default_weight_[ synapse_indx ] = not syn_params.known( names::weight ); + default_delay_[ synapse_indx ] = not syn_params.known( names::delay ); // If neither weight nor delay are given in the dict, we handle this separately. Important for // hom_w synapses, on which weight cannot be set. However, we use default weight and delay for @@ -534,41 +521,40 @@ nest::BipartiteConnBuilder::set_default_weight_or_delay_( DictionaryDatum syn_pa if ( not default_weight_and_delay_[ synapse_indx ] ) { - weights_[ synapse_indx ] = syn_params->known( names::weight ) - ? ConnParameter::create( ( *syn_params )[ names::weight ], kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( ( *syn_defaults )[ names::weight ], kernel().vp_manager.get_num_threads() ); + weights_[ synapse_indx ] = syn_params.known( names::weight ) + ? ConnParameter::create( syn_params.at( names::weight ), kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( syn_defaults[ names::weight ], kernel().vp_manager.get_num_threads() ); register_parameters_requiring_skipping_( *weights_[ synapse_indx ] ); - delays_[ synapse_indx ] = syn_params->known( names::delay ) - ? ConnParameter::create( ( *syn_params )[ names::delay ], kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( ( *syn_defaults )[ names::delay ], kernel().vp_manager.get_num_threads() ); + delays_[ synapse_indx ] = syn_params.known( names::delay ) + ? ConnParameter::create( syn_params.at( names::delay ), kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( syn_defaults[ names::delay ], kernel().vp_manager.get_num_threads() ); } else if ( default_weight_[ synapse_indx ] ) { - delays_[ synapse_indx ] = syn_params->known( names::delay ) - ? ConnParameter::create( ( *syn_params )[ names::delay ], kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( ( *syn_defaults )[ names::delay ], kernel().vp_manager.get_num_threads() ); + delays_[ synapse_indx ] = syn_params.known( names::delay ) + ? ConnParameter::create( syn_params.at( names::delay ), kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( syn_defaults[ names::delay ], kernel().vp_manager.get_num_threads() ); } register_parameters_requiring_skipping_( *delays_[ synapse_indx ] ); } void -nest::BipartiteConnBuilder::set_synapse_params( DictionaryDatum syn_defaults, - DictionaryDatum syn_params, +nest::BipartiteConnBuilder::set_synapse_params( const Dictionary& syn_defaults, + const Dictionary& syn_params, size_t synapse_indx ) { - for ( Dictionary::const_iterator default_it = syn_defaults->begin(); default_it != syn_defaults->end(); ++default_it ) + for ( [[maybe_unused]] const auto& [ param_name, unused ] : syn_defaults ) { - const Name param_name = default_it->first; if ( skip_syn_params_.find( param_name ) != skip_syn_params_.end() ) { continue; // weight, delay or other not-settable parameter } - if ( syn_params->known( param_name ) ) + if ( syn_params.known( param_name ) ) { synapse_params_[ synapse_indx ][ param_name ] = - ConnParameter::create( ( *syn_params )[ param_name ], kernel().vp_manager.get_num_threads() ); + ConnParameter::create( syn_params.at( param_name ), kernel().vp_manager.get_num_threads() ); register_parameters_requiring_skipping_( *synapse_params_[ synapse_indx ][ param_name ] ); } } @@ -577,52 +563,59 @@ nest::BipartiteConnBuilder::set_synapse_params( DictionaryDatum syn_defaults, // create it here once to avoid re-creating the object over and over again. for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { - param_dicts_[ synapse_indx ].push_back( new Dictionary() ); + param_dicts_[ synapse_indx ].emplace_back(); for ( auto param : synapse_params_[ synapse_indx ] ) { if ( param.second->provides_long() ) { - ( *param_dicts_[ synapse_indx ][ tid ] )[ param.first ] = Token( new IntegerDatum( 0 ) ); + param_dicts_[ synapse_indx ][ tid ][ param.first ] = 0; } else { - ( *param_dicts_[ synapse_indx ][ tid ] )[ param.first ] = Token( new DoubleDatum( 0.0 ) ); + param_dicts_[ synapse_indx ][ tid ][ param.first ] = 0.0; } } } } void -nest::BipartiteConnBuilder::set_structural_plasticity_parameters( std::vector< DictionaryDatum > syn_specs ) +nest::BipartiteConnBuilder::set_structural_plasticity_parameters( const std::vector< Dictionary >& syn_specs ) { + // We must check here if any syn_spec provided contains sp-related parameters bool have_structural_plasticity_parameters = false; for ( auto& syn_spec : syn_specs ) { - if ( syn_spec->known( names::pre_synaptic_element ) or syn_spec->known( names::post_synaptic_element ) ) + if ( syn_spec.known( names::pre_synaptic_element ) or syn_spec.known( names::post_synaptic_element ) ) { have_structural_plasticity_parameters = true; } } - if ( not have_structural_plasticity_parameters ) { return; } + // We now know that we have SP-parameters and can perform SP-specific checks and operations if ( syn_specs.size() > 1 ) { throw KernelException( "Structural plasticity can only be used with a single syn_spec." ); } - const DictionaryDatum syn_spec = syn_specs[ 0 ]; - if ( syn_spec->known( names::pre_synaptic_element ) xor syn_spec->known( names::post_synaptic_element ) ) + // We know now that we only have a single syn spec and work with that in what follows. + // We take a reference to avoid copying. This also ensures that access to the dictionary + // elements is properly registered in the actual dictionary passed in from the Python level. + const Dictionary& syn_spec = syn_specs[ 0 ]; + + // != is the correct way to express exclusive or in C ++."xor" is bitwise. + if ( syn_spec.known( names::pre_synaptic_element ) != syn_spec.known( names::post_synaptic_element ) ) { throw BadProperty( "Structural plasticity requires both a pre- and postsynaptic element." ); } - pre_synaptic_element_name_ = getValue< std::string >( syn_spec, names::pre_synaptic_element ); - post_synaptic_element_name_ = getValue< std::string >( syn_spec, names::post_synaptic_element ); + pre_synaptic_element_name_ = syn_spec.get< std::string >( names::pre_synaptic_element ); + post_synaptic_element_name_ = syn_spec.get< std::string >( names::post_synaptic_element ); + use_structural_plasticity_ = true; } @@ -652,8 +645,8 @@ nest::BipartiteConnBuilder::reset_delays_() nest::ThirdInBuilder::ThirdInBuilder( NodeCollectionPTR sources, NodeCollectionPTR third, - const DictionaryDatum& third_conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& third_conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, third, nullptr, third_conn_spec, syn_specs ) , source_third_gids_( kernel().vp_manager.get_num_threads(), nullptr ) , source_third_counts_( kernel().vp_manager.get_num_threads(), nullptr ) @@ -782,8 +775,8 @@ nest::ThirdInBuilder::connect_() nest::ThirdOutBuilder::ThirdOutBuilder( const NodeCollectionPTR third, const NodeCollectionPTR targets, ThirdInBuilder* third_in, - const DictionaryDatum& third_conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& third_conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( third, targets, nullptr, third_conn_spec, syn_specs ) , third_in_( third_in ) { @@ -792,8 +785,8 @@ nest::ThirdOutBuilder::ThirdOutBuilder( const NodeCollectionPTR third, nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCollectionPTR third, const NodeCollectionPTR targets, ThirdInBuilder* third_in, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : ThirdOutBuilder( third, targets, third_in, conn_spec, syn_specs ) , p_( 1.0 ) , random_pool_( true ) @@ -801,10 +794,19 @@ nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCo , targets_per_third_( targets->size() / third->size() ) , pools_( kernel().vp_manager.get_num_threads(), nullptr ) { - updateValue< double >( conn_spec, names::p, p_ ); - updateValue< long >( conn_spec, names::pool_size, pool_size_ ); + conn_spec.update_value( names::p, p_ ); + + // PYTEST-NG: Consider cleaner scheme for handling size_t vs long + long pool_size_tmp = static_cast< long >( pool_size_ ); + conn_spec.update_value( names::pool_size, pool_size_tmp ); + if ( pool_size_tmp < 1 or third->size() < pool_size_tmp ) + { + throw BadProperty( "Pool size 1 ≤ pool_size ≤ size of third-factor population required" ); + } + pool_size_ = static_cast< size_t >( pool_size_tmp ); + std::string pool_type; - if ( updateValue< std::string >( conn_spec, names::pool_type, pool_type ) ) + if ( conn_spec.update_value( names::pool_type, pool_type ) ) { if ( pool_type == "random" ) { @@ -825,11 +827,6 @@ nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCo throw BadProperty( "Conditional probability of third-factor connection 0 ≤ p_third_if_primary ≤ 1 required" ); } - if ( pool_size_ < 1 or third->size() < pool_size_ ) - { - throw BadProperty( "Pool size 1 ≤ pool_size ≤ size of third-factor population required" ); - } - if ( not( random_pool_ or ( targets->size() * pool_size_ == third->size() ) or ( pool_size_ == 1 and targets->size() % third->size() == 0 ) ) ) { @@ -948,8 +945,8 @@ nest::ThirdBernoulliWithPoolBuilder::get_first_pool_index_( const size_t target_ nest::OneToOneBuilder::OneToOneBuilder( const NodeCollectionPTR sources, const NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // make sure that target and source population have the same size @@ -1029,11 +1026,10 @@ nest::OneToOneBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1077,11 +1073,10 @@ nest::OneToOneBuilder::disconnect_() single_disconnect_( snode_id, *target, target_thread ); } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1124,11 +1119,10 @@ nest::OneToOneBuilder::sp_connect_() single_connect_( snode_id, *target, target_thread, rng ); } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1164,11 +1158,10 @@ nest::OneToOneBuilder::sp_disconnect_() single_disconnect_( snode_id, *target, target_thread ); } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1220,11 +1213,10 @@ nest::AllToAllBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1299,11 +1291,10 @@ nest::AllToAllBuilder::sp_connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1349,11 +1340,10 @@ nest::AllToAllBuilder::disconnect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1389,11 +1379,10 @@ nest::AllToAllBuilder::sp_disconnect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1401,27 +1390,27 @@ nest::AllToAllBuilder::sp_disconnect_() nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // check for potential errors - long n_sources = static_cast< long >( sources_->size() ); + const size_t n_sources = sources_->size(); if ( n_sources == 0 ) { throw BadProperty( "Source array must not be empty." ); } - ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::indegree ].datum() ); - if ( pd ) + auto indegree = conn_spec.at( names::indegree ); + if ( is_type< std::shared_ptr< nest::Parameter > >( indegree ) ) { - indegree_ = *pd; + indegree_ = boost::any_cast< ParameterPTR >( indegree ); // TODO: Checks of parameter range } else { // Assume indegree is a scalar - const long value = ( *conn_spec )[ names::indegree ]; - indegree_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); + const long value = conn_spec.get< long >( names::indegree ); + indegree_ = ParameterPTR( new ConstantParameter( value ) ); // verify that indegree is not larger than source population if multapses are disabled if ( not allow_multapses_ ) @@ -1432,7 +1421,7 @@ nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, } else if ( value == n_sources and not allow_autapses_ ) { - LOG( M_WARNING, + LOG( VerbosityLevel::WARNING, "FixedInDegreeBuilder::connect", "Multapses and autapses prohibited. When the sources and the targets " "have a non-empty intersection, the connect algorithm will enter an infinite loop." ); @@ -1441,7 +1430,7 @@ nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, if ( value > 0.9 * n_sources ) { - LOG( M_WARNING, + LOG( VerbosityLevel::WARNING, "FixedInDegreeBuilder::connect", "Multapses are prohibited and you request more than 90% connectivity. Expect long connecting times!" ); } @@ -1506,11 +1495,10 @@ nest::FixedInDegreeBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1566,8 +1554,8 @@ nest::FixedInDegreeBuilder::inner_connect_( const int tid, nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // check for potential errors @@ -1576,18 +1564,17 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, { throw BadProperty( "Target array must not be empty." ); } - ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::outdegree ].datum() ); - if ( pd ) + auto outdegree = conn_spec.at( names::outdegree ); + if ( is_type< std::shared_ptr< nest::Parameter > >( outdegree ) ) { - outdegree_ = *pd; + outdegree_ = boost::any_cast< ParameterPTR >( outdegree ); // TODO: Checks of parameter range } else { // Assume outdegree is a scalar - const long value = ( *conn_spec )[ names::outdegree ]; - - outdegree_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); + const long value = conn_spec.get< long >( names::outdegree ); + outdegree_ = ParameterPTR( new ConstantParameter( value ) ); // verify that outdegree is not larger than target population if multapses // are disabled @@ -1599,7 +1586,7 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, } else if ( value == n_targets and not allow_autapses_ ) { - LOG( M_WARNING, + LOG( VerbosityLevel::WARNING, "FixedOutDegreeBuilder::connect", "Multapses and autapses prohibited. When the sources and the targets " "have a non-empty intersection, the connect algorithm will enter an infinite loop." ); @@ -1608,7 +1595,7 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, if ( value > 0.9 * n_targets ) { - LOG( M_WARNING, + LOG( VerbosityLevel::WARNING, "FixedOutDegreeBuilder::connect", "Multapses are prohibited and you request more than 90% connectivity. Expect long connecting times!" ); } @@ -1684,11 +1671,10 @@ nest::FixedOutDegreeBuilder::connect_() single_connect_( snode_id, *target, tid, rng ); } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1697,10 +1683,10 @@ nest::FixedOutDegreeBuilder::connect_() nest::FixedTotalNumberBuilder::FixedTotalNumberBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) - , N_( ( *conn_spec )[ names::N ] ) + , N_( conn_spec.get< long >( names::N ) ) { // check for potential errors @@ -1855,11 +1841,10 @@ nest::FixedTotalNumberBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -1868,25 +1853,25 @@ nest::FixedTotalNumberBuilder::connect_() nest::BernoulliBuilder::BernoulliBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { - ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::p ].datum() ); - if ( pd ) + auto p = conn_spec.at( names::p ); + if ( is_type< std::shared_ptr< nest::Parameter > >( p ) ) { - p_ = *pd; + p_ = boost::any_cast< ParameterPTR >( p ); // TODO: Checks of parameter range } else { // Assume p is a scalar - const double value = ( *conn_spec )[ names::p ]; + const double value = conn_spec.get< double >( names::p ); if ( value < 0 or 1 < value ) { throw BadProperty( "Connection probability 0 <= p <= 1 required." ); } - p_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); + p_ = ParameterPTR( new ConstantParameter( value ) ); } } @@ -1939,11 +1924,10 @@ nest::BernoulliBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } // of omp parallel } @@ -1984,28 +1968,30 @@ nest::BernoulliBuilder::inner_connect_( const int tid, RngPtr rng, Node* target, nest::PoissonBuilder::PoissonBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { - ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::pairwise_avg_num_conns ].datum() ); - if ( pd ) + + auto p = conn_spec.at( names::pairwise_avg_num_conns ); + if ( is_type< std::shared_ptr< nest::Parameter > >( p ) ) { - pairwise_avg_num_conns_ = *pd; + pairwise_avg_num_conns_ = boost::any_cast< ParameterPTR >( p ); } else { // Assume pairwise_avg_num_conns is a scalar - const double value = ( *conn_spec )[ names::pairwise_avg_num_conns ]; + const double value = conn_spec.get< double >( names::pairwise_avg_num_conns ); if ( value < 0 ) { throw BadProperty( "Connection parameter 0 ≤ pairwise_avg_num_conns required." ); } - if ( not allow_multapses_ ) - { - throw BadProperty( "Multapses must be allowed for this connection rule." ); - } - pairwise_avg_num_conns_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); + pairwise_avg_num_conns_ = ParameterPTR( new ConstantParameter( value ) ); + } + + if ( not allow_multapses_ ) + { + throw BadProperty( "Multapses must be allowed for this connection rule." ); } } @@ -2055,11 +2041,9 @@ nest::PoissonBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + exceptions_raised_.at( tid ) = std::current_exception(); } } // of omp parallel } @@ -2102,10 +2086,10 @@ nest::PoissonBuilder::inner_connect_( const int tid, RngPtr rng, Node* target, s nest::SymmetricBernoulliBuilder::SymmetricBernoulliBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) - , p_( ( *conn_spec )[ names::p ] ) + , p_( conn_spec.get< double >( names::p ) ) { // This connector takes care of symmetric connections on its own creates_symmetric_connections_ = true; @@ -2217,11 +2201,10 @@ nest::SymmetricBernoulliBuilder::connect_() } } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } @@ -2230,8 +2213,8 @@ nest::SymmetricBernoulliBuilder::connect_() nest::SPBuilder::SPBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const DictionaryDatum& conn_spec, - const std::vector< DictionaryDatum >& syn_specs ) + const Dictionary& conn_spec, + const std::vector< Dictionary >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // Check that both pre and postsynaptic element are provided @@ -2246,8 +2229,8 @@ nest::SPBuilder::update_delay( long& d ) const { if ( get_default_delay() ) { - DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( get_synapse_model() ); - const double delay = getValue< double >( syn_defaults, "delay" ); + Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( get_synapse_model() ); + const double delay = syn_defaults.get< double >( "delay" ); d = Time( Time::ms( delay ) ).get_steps(); } } @@ -2258,11 +2241,11 @@ nest::SPBuilder::sp_connect( const std::vector< size_t >& sources, const std::ve connect_( sources, targets ); // check if any exceptions have been raised - for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) + for ( auto eptr : exceptions_raised_ ) { - if ( exceptions_raised_.at( tid ).get() ) + if ( eptr ) { - throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); + std::rethrow_exception( eptr ); } } } @@ -2322,11 +2305,10 @@ nest::SPBuilder::connect_( const std::vector< size_t >& sources, const std::vect single_connect_( *snode_id_it, *target, tid, rng ); } } - catch ( std::exception& err ) + catch ( ... ) { - // We must create a new exception here, err's lifetime ends at - // the end of the catch block. - exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); + // Capture the current exception object and create an std::exception_ptr + exceptions_raised_.at( tid ) = std::current_exception(); } } } diff --git a/nestkernel/conn_builder.h b/nestkernel/conn_builder.h index 801d4bb355..ba70751027 100644 --- a/nestkernel/conn_builder.h +++ b/nestkernel/conn_builder.h @@ -853,8 +853,8 @@ inline void BipartiteConnBuilder::skip_conn_parameter_( size_t target_thread, size_t n_skip ) { for ( std::vector< ConnParameter* >::iterator it = parameters_requiring_skipping_.begin(); - it != parameters_requiring_skipping_.end(); - ++it ) + it != parameters_requiring_skipping_.end(); + ++it ) { ( *it )->skip( target_thread, n_skip ); } diff --git a/nestkernel/connection_creator.cpp b/nestkernel/connection_creator.cpp index 21b94e3153..a8c52d661d 100644 --- a/nestkernel/connection_creator.cpp +++ b/nestkernel/connection_creator.cpp @@ -21,12 +21,14 @@ */ #include "connection_creator.h" -#include "dictutils.h" + +#include "nest.h" +#include "spatial.h" namespace nest { -ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) +ConnectionCreator::ConnectionCreator( const Dictionary& dict ) : allow_autapses_( true ) , allow_multapses_( true ) , allow_oversized_( false ) @@ -37,58 +39,61 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) , weight_() , delay_() { - Name connection_type; + std::string connection_type; - updateValue< std::string >( dict, names::connection_type, connection_type ); - updateValue< bool >( dict, names::allow_autapses, allow_autapses_ ); - updateValue< bool >( dict, names::allow_multapses, allow_multapses_ ); - updateValue< bool >( dict, names::allow_oversized_mask, allow_oversized_ ); + dict.update_value( names::connection_type, connection_type ); + dict.update_value( names::allow_autapses, allow_autapses_ ); + dict.update_value( names::allow_multapses, allow_multapses_ ); + dict.update_value( names::allow_oversized_mask, allow_oversized_ ); // Need to store number of connections in a temporary variable to be able to detect negative values. - - if ( dict->known( names::number_of_connections ) ) + if ( dict.known( names::number_of_connections ) ) { - ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *dict )[ names::number_of_connections ].datum() ); - if ( pd ) + if ( is_type< ParameterPTR >( dict.at( names::number_of_connections ) ) ) { - number_of_connections_ = *pd; + dict.update_value< ParameterPTR >( names::number_of_connections, number_of_connections_ ); } else { // Assume indegree is a scalar. - const long value = ( *dict )[ names::number_of_connections ]; + const long value = dict.get< long >( names::number_of_connections ); if ( value < 0 ) { throw BadProperty( "Number of connections cannot be less than zero." ); } - number_of_connections_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); + number_of_connections_ = ParameterPTR( new ConstantParameter( value ) ); } } - - if ( dict->known( names::mask ) ) + if ( dict.known( names::mask ) ) { - mask_ = NestModule::create_mask( ( *dict )[ names::mask ] ); + mask_ = create_mask( dict.get< Dictionary >( names::mask ) ); } - if ( dict->known( names::kernel ) ) + if ( dict.known( names::kernel ) ) { - kernel_ = NestModule::create_parameter( ( *dict )[ names::kernel ] ); + kernel_ = create_parameter( dict.at( names::kernel ) ); } - if ( dict->known( names::synapse_parameters ) ) + + if ( dict.known( names::synapse_parameters ) ) { // If synapse_parameters exists, we have collocated synapses. - ArrayDatum* syn_params_dvd = dynamic_cast< ArrayDatum* >( ( *dict )[ names::synapse_parameters ].datum() ); - if ( not syn_params_dvd ) + std::vector< Dictionary > syn_params_dvd; + + try + { + dict.update_value( names::synapse_parameters, syn_params_dvd ); + } + catch ( const nest::TypeMismatch& ) { + // Give a more helpful message if the provided type is wrong. throw BadProperty( "synapse_parameters must be list of dictionaries" ); } - param_dicts_.resize( syn_params_dvd->size() ); + param_dicts_.resize( syn_params_dvd.size() ); auto param_dict = param_dicts_.begin(); - for ( auto synapse_datum = syn_params_dvd->begin(); synapse_datum < syn_params_dvd->end(); - ++synapse_datum, ++param_dict ) + for ( auto syn_param_it = syn_params_dvd.begin(); syn_param_it < syn_params_dvd.end(); + ++syn_param_it, ++param_dict ) { - auto syn_param = dynamic_cast< DictionaryDatum* >( synapse_datum->datum() ); - extract_params_( *syn_param, *param_dict ); + extract_params_( *syn_param_it, *param_dict ); } } else @@ -99,34 +104,31 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) extract_params_( dict, param_dicts_[ 0 ] ); } - ALL_ENTRIES_ACCESSED( *dict, "ConnectionCreator", "Unread dictionary entries: " ); - // Set default synapse_model, weight and delay if not given explicitly if ( synapse_model_.empty() ) { synapse_model_ = { kernel().model_manager.get_synapse_model_id( "static_synapse" ) }; } - DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_[ 0 ] ); + Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_[ 0 ] ); if ( weight_.empty() ) { - weight_ = { NestModule::create_parameter( ( *syn_defaults )[ names::weight ] ) }; + weight_ = { create_parameter( syn_defaults[ names::weight ] ) }; } if ( delay_.empty() ) { - if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) + if ( not syn_defaults.get< bool >( names::has_delay ) ) { - delay_ = { NestModule::create_parameter( numerics::nan ) }; + delay_ = { create_parameter( numerics::nan ) }; } else { - delay_ = { NestModule::create_parameter( ( *syn_defaults )[ names::delay ] ) }; + delay_ = { create_parameter( syn_defaults[ names::delay ] ) }; } } if ( connection_type == names::pairwise_bernoulli_on_source ) { - - if ( dict->known( names::number_of_connections ) ) + if ( dict.known( names::number_of_connections ) ) { type_ = Fixed_indegree; } @@ -141,8 +143,7 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) } else if ( connection_type == names::pairwise_bernoulli_on_target ) { - - if ( dict->known( names::number_of_connections ) ) + if ( dict.known( names::number_of_connections ) ) { type_ = Fixed_outdegree; } @@ -158,52 +159,49 @@ ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) } void -ConnectionCreator::extract_params_( const DictionaryDatum& dict_datum, std::vector< DictionaryDatum >& params ) +ConnectionCreator::extract_params_( const Dictionary& dict, std::vector< Dictionary >& params ) { - if ( not dict_datum->known( names::synapse_model ) ) - { - dict_datum->insert( names::synapse_model, "static_synapse" ); - } - std::string syn_name = ( *dict_datum )[ names::synapse_model ]; + const std::string syn_name = dict.known( names::synapse_model ) ? dict.get< std::string >( names::synapse_model ) + : std::string( "static_synapse" ); // The following call will throw "UnknownSynapseType" if syn_name is not naming a known model const size_t synapse_model_id = kernel().model_manager.get_synapse_model_id( syn_name ); synapse_model_.push_back( synapse_model_id ); - DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id ); - if ( dict_datum->known( names::weight ) ) + Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id ); + if ( dict.known( names::weight ) ) { - weight_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::weight ] ) ); + weight_.push_back( create_parameter( dict.at( names::weight ) ) ); } else { - weight_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::weight ] ) ); + weight_.push_back( create_parameter( syn_defaults[ names::weight ] ) ); } - if ( dict_datum->known( names::delay ) ) + if ( dict.known( names::delay ) ) { - delay_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::delay ] ) ); + delay_.push_back( create_parameter( dict.at( names::delay ) ) ); } else { - if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) + if ( not syn_defaults.get< bool >( names::has_delay ) ) { - delay_.push_back( NestModule::create_parameter( numerics::nan ) ); + delay_.push_back( create_parameter( numerics::nan ) ); } else { - delay_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::delay ] ) ); + delay_.push_back( create_parameter( syn_defaults[ names::delay ] ) ); } } - DictionaryDatum syn_dict = new Dictionary(); + Dictionary syn_dict; // Using a lambda function here instead of updateValue because updateValue causes // problems when setting a value to a dictionary-entry in syn_dict. - auto copy_long_if_known = [ &syn_dict, &dict_datum ]( const Name& name ) -> void + auto copy_long_if_known = [ &syn_dict, &dict ]( const std::string& name ) -> void { - if ( dict_datum->known( name ) ) + if ( dict.known( name ) ) { - ( *syn_dict )[ name ] = getValue< long >( dict_datum, name ); + syn_dict[ name ] = dict.get< long >( name ); } }; copy_long_if_known( names::synapse_label ); diff --git a/nestkernel/connection_creator_impl.h b/nestkernel/connection_creator_impl.h index e094ab59d5..39e3945953 100644 --- a/nestkernel/connection_creator_impl.h +++ b/nestkernel/connection_creator_impl.h @@ -531,8 +531,8 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, // Collect probabilities for the sources for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions.begin(); - iter != positions.end(); - ++iter ) + 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 ) ); @@ -664,8 +664,8 @@ ConnectionCreator::fixed_indegree_( Layer< D >& source, // Collect probabilities for the sources for ( typename std::vector< std::pair< Position< D >, size_t > >::iterator iter = positions->begin(); - iter != positions->end(); - ++iter ) + 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 ) ); diff --git a/nestkernel/connection_manager.cpp b/nestkernel/connection_manager.cpp index de9307ce1a..a02598cfad 100644 --- a/nestkernel/connection_manager.cpp +++ b/nestkernel/connection_manager.cpp @@ -1028,7 +1028,7 @@ nest::ConnectionManager::trigger_update_weight( const long vt_id, const size_t tid = kernel().vp_manager.get_thread_id(); for ( std::vector< ConnectorBase* >::iterator it = connections_[ tid ].begin(); it != connections_[ tid ].end(); - ++it ) + ++it ) { if ( *it ) { @@ -1315,8 +1315,8 @@ nest::ConnectionManager::get_connections_from_sources_( const size_t tid, else { for ( std::vector< size_t >::const_iterator t_node_id = target_neuron_node_ids.begin(); - t_node_id != target_neuron_node_ids.end(); - ++t_node_id ) + t_node_id != target_neuron_node_ids.end(); + ++t_node_id ) { // target_table_devices_ contains connections both to and from // devices. First we get connections from devices. @@ -1324,8 +1324,8 @@ nest::ConnectionManager::get_connections_from_sources_( const size_t tid, source_node_id, *t_node_id, tid, syn_id, synapse_label, conns_in_thread ); } for ( std::vector< size_t >::const_iterator t_node_id = target_device_node_ids.begin(); - t_node_id != target_device_node_ids.end(); - ++t_node_id ) + t_node_id != target_device_node_ids.end(); + ++t_node_id ) { // Then, we get connections to devices. target_table_devices_.get_connections_to_devices_( diff --git a/nestkernel/eprop_archiving_node_impl.h b/nestkernel/eprop_archiving_node_impl.h index 7c4c60a52e..8b848585b2 100644 --- a/nestkernel/eprop_archiving_node_impl.h +++ b/nestkernel/eprop_archiving_node_impl.h @@ -140,8 +140,8 @@ EpropArchivingNode< HistEntryT >::erase_used_eprop_history() 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 ) + t <= ( update_history_.end() - 1 )->t_ and it_update_hist != update_history_.end(); + t += update_interval ) { if ( it_update_hist->t_ == t ) { diff --git a/nestkernel/event_delivery_manager.cpp b/nestkernel/event_delivery_manager.cpp index 8ba790b740..91f0c14684 100644 --- a/nestkernel/event_delivery_manager.cpp +++ b/nestkernel/event_delivery_manager.cpp @@ -771,7 +771,7 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik } } } // if-else not compressed - } // for rank + } // for rank } @@ -1003,7 +1003,7 @@ EventDeliveryManager::collocate_target_data_buffers_( const size_t tid, } return is_source_table_read; } // of else - } // of while(true) + } // of while(true) } bool diff --git a/nestkernel/kernel_manager.cpp b/nestkernel/kernel_manager.cpp index e31cea89b4..775d6757a9 100644 --- a/nestkernel/kernel_manager.cpp +++ b/nestkernel/kernel_manager.cpp @@ -25,6 +25,121 @@ nest::KernelManager* nest::KernelManager::kernel_manager_instance_ = nullptr; + +Dictionary +nest::KernelManager::get_build_info_() +{ + // Exit codes + constexpr unsigned int EXITCODE_UNKNOWN_ERROR = 10; + constexpr unsigned int EXITCODE_USERABORT = 15; + constexpr unsigned int EXITCODE_EXCEPTION = 125; + constexpr unsigned int EXITCODE_SCRIPTERROR = 126; + constexpr unsigned int EXITCODE_FATAL = 127; + + // The range 200-215 is reserved for test skipping exitcodes. Any new codes must + // also be added to testsuite/do_tests_sh.in. + constexpr unsigned int EXITCODE_SKIPPED = 200; + constexpr unsigned int EXITCODE_SKIPPED_NO_MPI = 201; + constexpr unsigned int EXITCODE_SKIPPED_HAVE_MPI = 202; + constexpr unsigned int EXITCODE_SKIPPED_NO_THREADING = 203; + constexpr unsigned int EXITCODE_SKIPPED_NO_GSL = 204; + constexpr unsigned int EXITCODE_SKIPPED_NO_MUSIC = 205; + + Dictionary build_info; + + build_info[ "version" ] = std::string( NEST_VERSION ); + build_info[ "exitcode" ] = EXIT_SUCCESS; + build_info[ "built" ] = std::string( String::compose( "%1 %2", __DATE__, __TIME__ ) ); + build_info[ "datadir" ] = std::string( NEST_INSTALL_PREFIX "/" NEST_INSTALL_DATADIR ); + build_info[ "docdir" ] = std::string( NEST_INSTALL_PREFIX "/" NEST_INSTALL_DOCDIR ); + build_info[ "prefix" ] = std::string( NEST_INSTALL_PREFIX ); + build_info[ "host" ] = std::string( NEST_HOST ); + build_info[ "hostos" ] = std::string( NEST_HOSTOS ); + build_info[ "hostvendor" ] = std::string( NEST_HOSTVENDOR ); + build_info[ "hostcpu" ] = std::string( NEST_HOSTCPU ); + +#ifdef _OPENMP + build_info[ "have_threads" ] = true; + build_info[ "threads_model" ] = std::string( "openmp" ); +#else + build_info[ "have_threads" ] = false; +#endif + +#ifdef HAVE_MPI + build_info[ "have_mpi" ] = true; + build_info[ "mpiexec" ] = std::string( MPIEXEC ); + build_info[ "mpiexec_numproc_flag" ] = std::string( MPIEXEC_NUMPROC_FLAG ); + build_info[ "mpiexec_max_numprocs" ] = std::string( MPIEXEC_MAX_NUMPROCS ); + build_info[ "mpiexec_preflags" ] = std::string( MPIEXEC_PREFLAGS ); + build_info[ "mpiexec_postflags" ] = std::string( MPIEXEC_POSTFLAGS ); +#else + build_info[ "have_mpi" ] = false; +#endif + +#ifdef HAVE_GSL + build_info[ "have_gsl" ] = true; +#else + build_info[ "have_gsl" ] = false; +#endif + +#ifdef HAVE_BOOST + build_info[ "have_boost" ] = true; +#else + build_info[ "have_boost" ] = false; +#endif + +#ifdef HAVE_MUSIC + build_info[ "have_music" ] = true; +#else + build_info[ "have_music" ] = false; +#endif + +#ifdef HAVE_LIBNEUROSIM + build_info[ "have_libneurosim" ] = true; +#else + build_info[ "have_libneurosim" ] = false; +#endif + +#ifdef HAVE_SIONLIB + build_info[ "have_sionlib" ] = true; +#else + build_info[ "have_sionlib" ] = false; +#endif + +#ifdef HAVE_HDF5 + build_info[ "have_hdf5" ] = true; +#else + build_info[ "have_hdf5" ] = false; +#endif + +#ifdef NDEBUG + build_info[ "ndebug" ] = true; +#else + build_info[ "ndebug" ] = false; +#endif + + Dictionary exitcodes; + + exitcodes[ "success" ] = EXIT_SUCCESS; + exitcodes[ "skipped" ] = EXITCODE_SKIPPED; + exitcodes[ "skipped_no_mpi" ] = EXITCODE_SKIPPED_NO_MPI; + exitcodes[ "skipped_have_mpi" ] = EXITCODE_SKIPPED_HAVE_MPI; + exitcodes[ "skipped_no_threading" ] = EXITCODE_SKIPPED_NO_THREADING; + exitcodes[ "skipped_no_gsl" ] = EXITCODE_SKIPPED_NO_GSL; + exitcodes[ "skipped_no_music" ] = EXITCODE_SKIPPED_NO_MUSIC; + exitcodes[ "scripterror" ] = EXITCODE_SCRIPTERROR; + exitcodes[ "abort" ] = NEST_EXITCODE_ABORT; + exitcodes[ "userabort" ] = EXITCODE_USERABORT; + exitcodes[ "segfault" ] = NEST_EXITCODE_SEGFAULT; + exitcodes[ "exception" ] = EXITCODE_EXCEPTION; + exitcodes[ "fatal" ] = EXITCODE_FATAL; + exitcodes[ "unknownerror" ] = EXITCODE_UNKNOWN_ERROR; + + build_info[ "test_exitcodes" ] = exitcodes; + + return build_info; +} + void nest::KernelManager::create_kernel_manager() { @@ -39,13 +154,6 @@ nest::KernelManager::create_kernel_manager() #pragma omp barrier } -void -nest::KernelManager::destroy_kernel_manager() -{ - kernel_manager_instance_->logging_manager.set_logging_level( M_QUIET ); - delete kernel_manager_instance_; -} - nest::KernelManager::KernelManager() : fingerprint_( 0 ) , logging_manager() @@ -183,7 +291,7 @@ nest::KernelManager::change_number_of_threads( size_t new_num_threads ) } void -nest::KernelManager::set_status( const DictionaryDatum& dict ) +nest::KernelManager::set_status( const Dictionary& dict ) { assert( is_initialized() ); @@ -194,7 +302,7 @@ nest::KernelManager::set_status( const DictionaryDatum& dict ) } void -nest::KernelManager::get_status( DictionaryDatum& dict ) +nest::KernelManager::get_status( Dictionary& dict ) { assert( is_initialized() ); @@ -203,6 +311,21 @@ nest::KernelManager::get_status( DictionaryDatum& dict ) manager->get_status( dict ); } + dict[ "build_info" ] = get_build_info_(); + if ( NEST_HOSTOS == std::string( "linux" ) ) + { + dict[ "memory_size" ] = get_memsize_linux_(); + } + else if ( NEST_HOSTOS == std::string( "darwin" ) ) + { + dict[ "memory_size" ] = get_memsize_darwin_(); + } + else + { + // Not available for this OS. + dict[ "memory_size" ] = -1; + } + sw_omp_synchronization_construction_.get_status( dict, names::time_omp_synchronization_construction, names::time_omp_synchronization_construction_cpu ); sw_omp_synchronization_simulation_.get_status( @@ -219,3 +342,80 @@ nest::KernelManager::write_to_dump( const std::string& msg ) dump_ << msg << std::endl << std::flush; } } + +#ifdef __linux__ + +#include +#include +size_t +nest::KernelManager::get_memsize_linux_() const +{ + // code based on mistral.ai + std::ifstream file( "/proc/self/status" ); + if ( not file.is_open() ) + { + throw std::runtime_error( "Could not open /proc/self/status" ); + } + + std::string line; + while ( std::getline( file, line ) ) + { + if ( line.rfind( "VmSize:", 0 ) == 0 ) + { + std::istringstream stream( line ); + std::string key; + size_t value; + std::string unit; + stream >> key >> value >> unit; + file.close(); + if ( unit != "kB" ) + { + throw std::runtime_error( "VmSize not reported in kB" ); + } + return value; + } + } + + file.close(); + throw std::runtime_error( "VmSize not found in /proc/self/status" ); +} + +#else + +size_t +nest::KernelManager::get_memsize_linux_() const +{ + assert( false || "Only implemented on Linux systems." ); + return 0; +} + +#endif + + +#if defined __APPLE__ + +#include +size_t +nest::KernelManager::get_memsize_darwin_() const +{ + struct task_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + + kern_return_t result = task_info( mach_task_self(), TASK_BASIC_INFO, ( task_info_t ) &t_info, &t_info_count ); + assert( result == KERN_SUCCESS || "Problem occurred during getting of task_info." ); + + // For macOS, vmsize is not informative, it is an extremly large address range, usually O(2^40). + // resident_size gives the most reasonable information. Information is in bytes, thus divide. + return t_info.resident_size / 1024; +} + +#else + +size_t +nest::KernelManager::get_memsize_darwin_() const +{ + assert( false || "Only implemented on macOS." ); + return 0; +} + +#endif diff --git a/nestkernel/layer_impl.h b/nestkernel/layer_impl.h index e24f571d08..81afe7741b 100644 --- a/nestkernel/layer_impl.h +++ b/nestkernel/layer_impl.h @@ -197,8 +197,8 @@ Layer< D >::do_get_global_positions_ntree_( NodeCollectionPTR node_collection ) 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 ) + from != cached_vector_->end(); + ++from ) { *to = *from; } @@ -265,7 +265,7 @@ Layer< D >::get_global_positions_vector( const MaskDatum& mask, 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 ) + ++iter ) { positions.push_back( *iter ); } @@ -294,8 +294,8 @@ 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 ) + it < this->node_collection_->end(); + ++it ) { out << ( *it ).node_id << ' '; get_position( ( *it ).nc_index ).print( out ); diff --git a/nestkernel/music_manager.cpp b/nestkernel/music_manager.cpp index ec237eca7d..3d68048329 100644 --- a/nestkernel/music_manager.cpp +++ b/nestkernel/music_manager.cpp @@ -256,15 +256,15 @@ void MUSICManager::publish_music_in_ports_() { for ( std::map< std::string, MusicEventHandler >::iterator it = music_event_in_portmap_.begin(); - it != music_event_in_portmap_.end(); - ++it ) + it != music_event_in_portmap_.end(); + ++it ) { it->second.publish_port(); } for ( std::map< std::string, MusicRateInHandler >::iterator it = music_rate_in_portmap_.begin(); - it != music_rate_in_portmap_.end(); - ++it ) + it != music_rate_in_portmap_.end(); + ++it ) { it->second.publish_port(); } @@ -274,15 +274,15 @@ void MUSICManager::update_music_event_handlers( Time const& origin, const long from, const long to ) { for ( std::map< std::string, MusicEventHandler >::iterator it = music_event_in_portmap_.begin(); - it != music_event_in_portmap_.end(); - ++it ) + it != music_event_in_portmap_.end(); + ++it ) { it->second.update( origin, from, to ); } for ( std::map< std::string, MusicRateInHandler >::iterator it = music_rate_in_portmap_.begin(); - it != music_rate_in_portmap_.end(); - ++it ) + it != music_rate_in_portmap_.end(); + ++it ) { it->second.update( origin, from, to ); } diff --git a/nestkernel/nest_time.h b/nestkernel/nest_time.h index f579af5659..ee88ed2fe9 100644 --- a/nestkernel/nest_time.h +++ b/nestkernel/nest_time.h @@ -297,21 +297,21 @@ class Time Time( tic t ) : tics( ( time_abs( t.t ) < LIM_MAX.tics ) ? t.t - : ( t.t < 0 ) ? LIM_NEG_INF.tics + : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) { } Time( step t ) : tics( ( time_abs( t.t ) < LIM_MAX.steps ) ? t.t * Range::TICS_PER_STEP - : ( t.t < 0 ) ? LIM_NEG_INF.tics + : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) { } Time( ms t ) : tics( ( time_abs( t.t ) < LIM_MAX.ms ) ? static_cast< tic_t >( t.t * Range::TICS_PER_MS + 0.5 ) - : ( t.t < 0 ) ? LIM_NEG_INF.tics + : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) { } diff --git a/nestkernel/nestmodule.cpp b/nestkernel/nestmodule.cpp index 56fa7ec848..90832964f0 100644 --- a/nestkernel/nestmodule.cpp +++ b/nestkernel/nestmodule.cpp @@ -2007,8 +2007,8 @@ NestModule::SelectNodesByMask_g_a_MFunction::execute( SLIInterpreter* i ) const MaskedLayer< 2 > ml = MaskedLayer< 2 >( *layer, mask, false, layer_nc ); for ( Ntree< 2, size_t >::masked_iterator it = ml.begin( Position< 2 >( anchor[ 0 ], anchor[ 1 ] ) ); - it != ml.end(); - ++it ) + it != ml.end(); + ++it ) { mask_node_ids.push_back( it->second ); } @@ -2024,8 +2024,8 @@ NestModule::SelectNodesByMask_g_a_MFunction::execute( SLIInterpreter* i ) const MaskedLayer< 3 > ml = MaskedLayer< 3 >( *layer, mask, false, layer_nc ); for ( Ntree< 3, size_t >::masked_iterator it = ml.begin( Position< 3 >( anchor[ 0 ], anchor[ 1 ], anchor[ 2 ] ) ); - it != ml.end(); - ++it ) + it != ml.end(); + ++it ) { mask_node_ids.push_back( it->second ); } diff --git a/nestkernel/node_collection.cpp b/nestkernel/node_collection.cpp index b4323921f4..03336e2b41 100644 --- a/nestkernel/node_collection.cpp +++ b/nestkernel/node_collection.cpp @@ -543,7 +543,7 @@ NodeCollection::to_array( const std::string& selection ) const node_ids.push_back( ( *it ).node_id ); } } // end critical - } // end parallel + } // end parallel } else { diff --git a/nestkernel/node_manager.cpp b/nestkernel/node_manager.cpp index 03a637494f..735e5620ef 100644 --- a/nestkernel/node_manager.cpp +++ b/nestkernel/node_manager.cpp @@ -735,8 +735,8 @@ NodeManager::print( std::ostream& out ) const const double node_id_range_width = 6 + 2 * max_node_id_width; for ( std::vector< modelrange >::const_iterator it = kernel().modelrange_manager.begin(); - it != kernel().modelrange_manager.end(); - ++it ) + it != kernel().modelrange_manager.end(); + ++it ) { const size_t first_node_id = it->get_first_node_id(); const size_t last_node_id = it->get_last_node_id(); diff --git a/nestkernel/parameter.h b/nestkernel/parameter.h index dfae3cfcb9..de71a57d35 100644 --- a/nestkernel/parameter.h +++ b/nestkernel/parameter.h @@ -761,7 +761,7 @@ class ConditionalParameter : public Parameter std::shared_ptr< Parameter > if_true, std::shared_ptr< Parameter > if_false ) : Parameter( condition->is_spatial() or if_true->is_spatial() or if_false->is_spatial(), - if_true->returns_int_only() and if_false->returns_int_only() ) + if_true->returns_int_only() and if_false->returns_int_only() ) , condition_( condition ) , if_true_( if_true ) , if_false_( if_false ) diff --git a/nestkernel/position.h b/nestkernel/position.h index 812239be92..9a33a67a93 100644 --- a/nestkernel/position.h +++ b/nestkernel/position.h @@ -805,7 +805,8 @@ Position< D, T >::length() const } template < int D, class T > -Position< D, T >::operator std::string() const +Position< D, T >:: +operator std::string() const { std::stringstream ss; ss << *this; diff --git a/nestkernel/ring_buffer_impl.h b/nestkernel/ring_buffer_impl.h index 76db8a6fb6..668fed04ca 100644 --- a/nestkernel/ring_buffer_impl.h +++ b/nestkernel/ring_buffer_impl.h @@ -28,7 +28,7 @@ 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 >() ) + std::array< double, num_channels >() ) { } diff --git a/nestkernel/simulation_manager.cpp b/nestkernel/simulation_manager.cpp index 44aeec3efd..3f0147ffd4 100644 --- a/nestkernel/simulation_manager.cpp +++ b/nestkernel/simulation_manager.cpp @@ -940,8 +940,8 @@ nest::SimulationManager::update_() // this loop may be empty for those threads // that do not have any nodes requiring wfr_update for ( std::vector< Node* >::const_iterator i = thread_local_wfr_nodes.begin(); - i != thread_local_wfr_nodes.end(); - ++i ) + i != thread_local_wfr_nodes.end(); + ++i ) { done_p = wfr_update_( *i ) and done_p; } @@ -1008,8 +1008,8 @@ nest::SimulationManager::update_() { #pragma omp barrier for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin(); - i != kernel().node_manager.get_local_nodes( tid ).end(); - ++i ) + i != kernel().node_manager.get_local_nodes( tid ).end(); + ++i ) { Node* node = i->get_node(); node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms() ); @@ -1023,8 +1023,8 @@ nest::SimulationManager::update_() } // Remove 10% of the vacant elements for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin(); - i != kernel().node_manager.get_local_nodes( tid ).end(); - ++i ) + i != kernel().node_manager.get_local_nodes( tid ).end(); + ++i ) { Node* node = i->get_node(); node->decay_synaptic_elements_vacant(); @@ -1122,8 +1122,8 @@ nest::SimulationManager::update_() // End of the slice, we update the number of synaptic elements for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin(); - i != kernel().node_manager.get_local_nodes( tid ).end(); - ++i ) + i != kernel().node_manager.get_local_nodes( tid ).end(); + ++i ) { Node* node = i->get_node(); node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + to_step_ ) ).get_ms() ); diff --git a/nestkernel/sonata_connector.cpp b/nestkernel/sonata_connector.cpp index b44ae89640..6320e437d3 100644 --- a/nestkernel/sonata_connector.cpp +++ b/nestkernel/sonata_connector.cpp @@ -479,7 +479,7 @@ SonataConnector::connect_chunk_( const hsize_t hyperslab_size, const hsize_t off weight ); } // end for - } // end try + } // end try catch ( std::exception& err ) { diff --git a/nestkernel/source_table.cpp b/nestkernel/source_table.cpp index 5be1b6fa4e..fd7bd75d76 100644 --- a/nestkernel/source_table.cpp +++ b/nestkernel/source_table.cpp @@ -252,8 +252,8 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t if ( not is_primary ) { for ( BlockVector< Source >::const_iterator source_cit = sources_[ tid ][ syn_id ].begin(); - source_cit != sources_[ tid ][ syn_id ].end(); - ++source_cit ) + source_cit != sources_[ tid ][ syn_id ].end(); + ++source_cit ) { #pragma omp critical { @@ -274,8 +274,8 @@ nest::SourceTable::compute_buffer_pos_for_unique_secondary_sources( const size_t for ( std::set< std::pair< size_t, size_t > >::const_iterator cit = ( *unique_secondary_source_node_id_syn_id ).begin(); - cit != ( *unique_secondary_source_node_id_syn_id ).end(); - ++cit ) + 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 event_size = kernel().model_manager.get_secondary_event_prototype( cit->second, tid )->size(); @@ -561,7 +561,7 @@ nest::SourceTable::fill_compressed_spike_data( for ( synindex syn_id = 0; syn_id < kernel().model_manager.get_num_connection_models(); ++syn_id ) { for ( size_t target_thread = 0; target_thread < static_cast< size_t >( compressible_sources_.size() ); - ++target_thread ) + ++target_thread ) { for ( const auto& connection : compressible_sources_[ target_thread ][ syn_id ] ) { @@ -589,7 +589,7 @@ nest::SourceTable::fill_compressed_spike_data( compressible_sources_[ target_thread ][ syn_id ].clear(); } // for target_thread - } // for syn_id + } // for syn_id } // Argument name only needed if full logging is activated. Macro-protect to avoid unused argument warning. @@ -598,8 +598,7 @@ nest::SourceTable::dump_compressed_spike_data( const std::vector< std::vector< std::vector< SpikeData > > >& FULL_LOGGING_ONLY( compressed_spike_data ) ) const { FULL_LOGGING_ONLY( - for ( const auto& tab - : compressed_spike_data_map_ ) { + for ( const auto& tab : compressed_spike_data_map_ ) { for ( const auto& entry : tab ) { kernel().write_to_dump( String::compose( "csdm : r%1 t%2 s%3 sx%4 tt%5", @@ -611,8 +610,7 @@ nest::SourceTable::dump_compressed_spike_data( } } - for ( const auto& tab - : compressed_spike_data ) { + for ( const auto& tab : compressed_spike_data ) { for ( size_t six = 0; six < tab.size(); ++six ) { for ( size_t tx = 0; tx < tab[ six ].size(); ++tx ) diff --git a/nestkernel/source_table.h b/nestkernel/source_table.h index 55f48756ba..4e3618439e 100644 --- a/nestkernel/source_table.h +++ b/nestkernel/source_table.h @@ -500,8 +500,8 @@ SourceTable::num_unique_sources( const size_t tid, const synindex syn_id ) const size_t n = 0; size_t last_source = 0; for ( BlockVector< Source >::const_iterator cit = sources_[ tid ][ syn_id ].begin(); - cit != sources_[ tid ][ syn_id ].end(); - ++cit ) + cit != sources_[ tid ][ syn_id ].end(); + ++cit ) { if ( last_source != ( *cit ).get_node_id() ) { diff --git a/nestkernel/spatial.cpp b/nestkernel/spatial.cpp index 8063eab1c3..87e4c7e6bd 100644 --- a/nestkernel/spatial.cpp +++ b/nestkernel/spatial.cpp @@ -23,6 +23,8 @@ #include "spatial.h" // C++ includes: +#include +#include #include #include @@ -33,12 +35,8 @@ #include "exceptions.h" #include "kernel_manager.h" #include "nest.h" -#include "nestmodule.h" #include "node.h" -// Includes from sli: -#include "sliexceptions.h" - // Includes from spatial: #include "grid_layer.h" #include "layer_impl.h" @@ -68,25 +66,25 @@ get_layer( NodeCollectionPTR nc ) } NodeCollectionPTR -create_layer( const DictionaryDatum& layer_dict ) +create_layer( const Dictionary& layer_dict ) { - layer_dict->clear_access_flags(); + layer_dict.init_access_flags(); NodeCollectionPTR layer = AbstractLayer::create_layer( layer_dict ); - ALL_ENTRIES_ACCESSED( *layer_dict, "nest::CreateLayer", "Unread dictionary entries: " ); + layer_dict.all_entries_accessed( "CreateLayer", "params" ); return layer; } -ArrayDatum +std::vector< std::vector< double > > get_position( NodeCollectionPTR layer_nc ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); - ArrayDatum result; + std::vector< std::vector< double > > result; result.reserve( layer_nc->size() ); for ( NodeCollection::const_iterator it = layer_nc->begin(); it < layer_nc->end(); ++it ) @@ -99,7 +97,7 @@ get_position( NodeCollectionPTR layer_nc ) } const long lid = node_id - first_node_id; - Token arr = layer->get_position_vector( lid ); + const auto arr = layer->get_position_vector( lid ); result.push_back( arr ); } @@ -133,17 +131,17 @@ get_position( const size_t node_id ) return pos_vec; } -ArrayDatum +std::vector< std::vector< double > > displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) { - ArrayDatum layer_to_positions = get_position( layer_to_nc ); + auto layer_to_positions = get_position( layer_to_nc ); AbstractLayerPTR layer_from = get_layer( layer_from_nc ); NodeCollectionMetadataPTR meta = layer_from_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); int counter = 0; - ArrayDatum result; + std::vector< std::vector< double > > result; // If layer_from has size equal to one, but layer_to do not, we want the displacement between every node // in layer_to against the one in layer_from. Likewise if layer_to has size 1 and layer_from do not. @@ -157,11 +155,9 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; // If layer_from has size 1, we need to iterate over the layer_to positions - for ( Token const* it = layer_to_positions.begin(); it != layer_to_positions.end(); ++it ) + for ( auto& pos : layer_to_positions ) { - std::vector< double > pos = getValue< std::vector< double > >( *it ); - Token disp = layer_from->compute_displacement( pos, lid ); - result.push_back( disp ); + result.push_back( layer_from->compute_displacement( pos, lid ) ); } } else @@ -175,10 +171,8 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) } const long lid = node_id - first_node_id; - - std::vector< double > pos = getValue< std::vector< double > >( layer_to_positions[ counter ] ); - Token disp = layer_from->compute_displacement( pos, lid ); - result.push_back( disp ); + const auto pos = layer_to_positions[ counter ]; + result.push_back( layer_from->compute_displacement( pos, lid ) ); // We only iterate the layer_to positions vector if it has more than one // element. @@ -192,15 +186,15 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) return result; } -ArrayDatum -displacement( NodeCollectionPTR layer_nc, const ArrayDatum point ) +std::vector< std::vector< double > > +displacement( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > >& point ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); int counter = 0; - ArrayDatum result; + std::vector< std::vector< double > > result; for ( NodeCollection::const_iterator it = layer_nc->begin(); it != layer_nc->end(); ++it ) { size_t node_id = ( *it ).node_id; @@ -211,9 +205,8 @@ displacement( NodeCollectionPTR layer_nc, const ArrayDatum point ) const long lid = node_id - first_node_id; - std::vector< double > pos = getValue< std::vector< double > >( point[ counter ] ); - Token disp = layer->compute_displacement( pos, lid ); - result.push_back( disp ); + const auto pos = point[ counter ]; + result.push_back( layer->compute_displacement( pos, lid ) ); // We only iterate the positions vector if it has more than one // element. @@ -228,7 +221,12 @@ displacement( NodeCollectionPTR layer_nc, const ArrayDatum point ) std::vector< double > distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) { - ArrayDatum layer_to_positions = get_position( layer_to_nc ); + if ( layer_to_nc->size() != 1 and layer_from_nc->size() != 1 and not( layer_to_nc->size() == layer_from_nc->size() ) ) + { + throw BadProperty( "NodeCollections must have equal length or one must have size 1." ); + } + + auto layer_to_positions = get_position( layer_to_nc ); AbstractLayerPTR layer_from = get_layer( layer_from_nc ); NodeCollectionMetadataPTR meta = layer_from_nc->get_metadata(); @@ -249,11 +247,9 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; // If layer_from has size 1, we need to iterate over the layer_to positions - for ( Token const* it = layer_to_positions.begin(); it != layer_to_positions.end(); ++it ) + for ( auto& pos : layer_to_positions ) { - std::vector< double > pos = getValue< std::vector< double > >( *it ); - double disp = layer_from->compute_distance( pos, lid ); - result.push_back( disp ); + result.push_back( layer_from->compute_distance( pos, lid ) ); } } else @@ -268,8 +264,8 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; - std::vector< double > pos = getValue< std::vector< double > >( layer_to_positions[ counter ] ); - double disp = layer_from->compute_distance( pos, lid ); + const auto pos = layer_to_positions[ counter ]; + const double disp = layer_from->compute_distance( pos, lid ); result.push_back( disp ); // We only iterate the layer_to positions vector if it has more than one @@ -285,7 +281,7 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) } std::vector< double > -distance( NodeCollectionPTR layer_nc, const ArrayDatum point ) +distance( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > >& point ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); @@ -303,7 +299,7 @@ distance( NodeCollectionPTR layer_nc, const ArrayDatum point ) const long lid = node_id - first_node_id; - std::vector< double > pos = getValue< std::vector< double > >( point[ counter ] ); + const auto pos = point[ counter ]; double disp = layer->compute_distance( pos, lid ); result.push_back( disp ); @@ -318,17 +314,15 @@ distance( NodeCollectionPTR layer_nc, const ArrayDatum point ) } std::vector< double > -distance( const ArrayDatum conns ) +distance( const std::vector< ConnectionID >& conns ) { std::vector< double > result; size_t num_conns = conns.size(); result.reserve( num_conns ); - for ( size_t conn_indx = 0; conn_indx < num_conns; ++conn_indx ) + for ( auto& conn_id : conns ) { - ConnectionDatum conn_id = getValue< ConnectionDatum >( conns.get( conn_indx ) ); - size_t src = conn_id.get_source_node_id(); auto src_position = get_position( src ); @@ -360,92 +354,222 @@ distance( const ArrayDatum conns ) return result; } -MaskDatum -create_mask( const DictionaryDatum& mask_dict ) +MaskPTR +create_mask( const Dictionary& mask_dict ) +{ + mask_dict.init_access_flags(); + + // The dictionary should contain one key which is the name of the + // mask type, and optionally the key 'anchor'. To find the unknown + // mask type key, we must loop through all keys. + bool has_anchor = false; + MaskPTR mask; + + for ( auto& kv : mask_dict ) + { + if ( kv.first == names::anchor ) + { + has_anchor = true; + } + else + { + mask = create_mask( kv.first, mask_dict.get< Dictionary >( kv.first ) ); + } + } + + if ( has_anchor ) + { + // The anchor may be an array of doubles (a spatial position). + // For grid layers only, it is also possible to provide an array of longs. + try + { + const std::vector< long >& anchor = mask_dict.get< std::vector< long > >( names::anchor ); + + switch ( anchor.size() ) + { + case 2: + try + { + auto& grid_mask_2d = dynamic_cast< GridMask< 2 >& >( *mask ); + grid_mask_2d.set_anchor( Position< 2, int >( anchor[ 0 ], anchor[ 1 ] ) ); + } + catch ( std::bad_cast& e ) + { + throw BadProperty( "Mask must be 2-dimensional grid mask." ); + } + break; + case 3: + try + { + auto& grid_mask_3d = dynamic_cast< GridMask< 3 >& >( *mask ); + grid_mask_3d.set_anchor( Position< 3, int >( anchor[ 0 ], anchor[ 1 ], anchor[ 2 ] ) ); + } + catch ( std::bad_cast& e ) + { + throw BadProperty( "Mask must be 3-dimensional grid mask." ); + } + break; + default: + throw BadProperty( "Anchor must be 2- or 3-dimensional." ); + } + } + catch ( TypeMismatch& e ) + { + std::vector< double > double_anchor = mask_dict.get< std::vector< double > >( names::anchor ); + std::shared_ptr< AbstractMask > amask; + + switch ( double_anchor.size() ) + { + case 2: + amask = std::shared_ptr< AbstractMask >( + new AnchoredMask< 2 >( dynamic_cast< Mask< 2 >& >( *mask ), double_anchor ) ); + break; + case 3: + amask = std::shared_ptr< AbstractMask >( + new AnchoredMask< 3 >( dynamic_cast< Mask< 3 >& >( *mask ), double_anchor ) ); + break; + default: + throw BadProperty( "Anchor must be 2- or 3-dimensional." ); + } + + mask = amask; + } + } + mask_dict.all_entries_accessed( "CreateMask", "mask_dict" ); + + return mask; +} + +NodeCollectionPTR +select_nodes_by_mask( const NodeCollectionPTR layer_nc, const std::vector< double >& anchor, const MaskPTR mask ) { - mask_dict->clear_access_flags(); + std::vector< size_t > mask_node_ids; - MaskDatum datum( NestModule::create_mask( mask_dict ) ); + const auto dim = anchor.size(); - ALL_ENTRIES_ACCESSED( *mask_dict, "nest::CreateMask", "Unread dictionary entries: " ); + if ( dim != 2 and dim != 3 ) + { + throw BadProperty( "Center must be 2- or 3-dimensional." ); + } + + AbstractLayerPTR abstract_layer = get_layer( layer_nc ); + + if ( dim == 2 ) + { + auto layer = dynamic_cast< Layer< 2 >* >( abstract_layer.get() ); + if ( not layer ) + { + throw TypeMismatch( "2D layer", "other type" ); + } - return datum; + auto ml = MaskedLayer< 2 >( *layer, mask, false, layer_nc ); + + for ( Ntree< 2, size_t >::masked_iterator it = ml.begin( Position< 2 >( anchor[ 0 ], anchor[ 1 ] ) ); + it != ml.end(); + ++it ) + { + mask_node_ids.push_back( it->second ); + } + } + else + { + auto layer = dynamic_cast< Layer< 3 >* >( abstract_layer.get() ); + if ( not layer ) + { + throw TypeMismatch( "3D layer", "other type" ); + } + + auto ml = MaskedLayer< 3 >( *layer, mask, false, layer_nc ); + + for ( Ntree< 3, size_t >::masked_iterator it = ml.begin( Position< 3 >( anchor[ 0 ], anchor[ 1 ], anchor[ 2 ] ) ); + it != ml.end(); + ++it ) + { + mask_node_ids.push_back( it->second ); + } + } + // Nodes must be sorted when creating a NodeCollection + std::sort( mask_node_ids.begin(), mask_node_ids.end() ); + return NodeCollection::create( mask_node_ids ); } -BoolDatum -inside( const std::vector< double >& point, const MaskDatum& mask ) +bool +inside( const std::vector< double >& point, const MaskPTR mask ) { return mask->inside( point ); } -MaskDatum -intersect_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) +MaskPTR +intersect_mask( const MaskPTR mask1, const MaskPTR mask2 ) { - return mask1->intersect_mask( *mask2 ); + return MaskPTR( mask1->intersect_mask( *mask2 ) ); } -MaskDatum -union_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) +MaskPTR +union_mask( const MaskPTR mask1, const MaskPTR mask2 ) { - return mask1->union_mask( *mask2 ); + return MaskPTR( mask1->union_mask( *mask2 ) ); } -MaskDatum -minus_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) +MaskPTR +minus_mask( const MaskPTR mask1, const MaskPTR mask2 ) { - return mask1->minus_mask( *mask2 ); + return MaskPTR( mask1->minus_mask( *mask2 ) ); } void -connect_layers( NodeCollectionPTR source_nc, NodeCollectionPTR target_nc, const DictionaryDatum& connection_dict ) +connect_layers( NodeCollectionPTR source_nc, NodeCollectionPTR target_nc, const Dictionary& connection_dict ) { AbstractLayerPTR source = get_layer( source_nc ); AbstractLayerPTR target = get_layer( target_nc ); - connection_dict->clear_access_flags(); + connection_dict.init_access_flags(); ConnectionCreator connector( connection_dict ); - ALL_ENTRIES_ACCESSED( *connection_dict, "nest::CreateLayers", "Unread dictionary entries: " ); + connection_dict.all_entries_accessed( "ConnectLayers", "connection_dict" ); kernel().node_manager.update_thread_local_node_data(); // Set flag before calling source->connect() in case exception is thrown after some connections have been created. kernel().connection_manager.set_connections_have_changed(); - source->connect( source_nc, target, target_nc, connector ); } void -dump_layer_nodes( NodeCollectionPTR layer_nc, OstreamDatum& out ) +dump_layer_nodes( const NodeCollectionPTR layer_nc, const std::string& filename ) { AbstractLayerPTR layer = get_layer( layer_nc ); - if ( out->good() ) + std::ofstream out( filename ); + if ( out.good() ) { - layer->dump_nodes( *out ); + layer->dump_nodes( out ); } + out.close(); } void -dump_layer_connections( const Token& syn_model, - NodeCollectionPTR source_layer_nc, - NodeCollectionPTR target_layer_nc, - OstreamDatum& out ) +dump_layer_connections( const NodeCollectionPTR source_layer_nc, + const NodeCollectionPTR target_layer_nc, + const std::string& syn_model, + const std::string& filename ) { AbstractLayerPTR source_layer = get_layer( source_layer_nc ); AbstractLayerPTR target_layer = get_layer( target_layer_nc ); - if ( out->good() ) + std::ofstream out( filename ); + if ( out.good() ) { - source_layer->dump_connections( *out, source_layer_nc, target_layer, syn_model ); + source_layer->dump_connections( out, source_layer_nc, target_layer, syn_model ); } + out.close(); } -DictionaryDatum +Dictionary get_layer_status( NodeCollectionPTR ) { assert( false and "not implemented" ); - return DictionaryDatum(); + return {}; } } // namespace nest diff --git a/nestkernel/stopwatch_impl.h b/nestkernel/stopwatch_impl.h index 2fac293267..7853d1a66d 100644 --- a/nestkernel/stopwatch_impl.h +++ b/nestkernel/stopwatch_impl.h @@ -56,7 +56,7 @@ Stopwatch< detailed_timer, threaded_timer >::start() cputime_timer_.start(); } } // use_timer_array - } // enable_timer + } // enable_timer } template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer > @@ -79,7 +79,7 @@ Stopwatch< detailed_timer, threaded_timer >::stop() cputime_timer_.stop(); } } // use_timer_array - } // enable_timer + } // enable_timer } template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer > @@ -156,7 +156,7 @@ Stopwatch< detailed_timer, threaded_timer >::print( const std::string& msg, walltime_timer_.print( msg, timeunit, os ); } } // use_timer_array - } // enable_timer + } // enable_timer } template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer > @@ -189,7 +189,7 @@ Stopwatch< detailed_timer, threaded_timer >::get_status( DictionaryDatum& d, def< double >( d, walltime_name, walltime_timer_.elapsed() ); def< double >( d, cputime_name, cputime_timer_.elapsed() ); } // use_timer_array - } // enable_timer + } // enable_timer } template < StopwatchGranularity detailed_timer, StopwatchParallelism threaded_timer > @@ -218,7 +218,7 @@ Stopwatch< detailed_timer, threaded_timer >::reset() cputime_timer_.reset(); } } // use_timer_array - } // enable_timer + } // enable_timer } } // namespace nest diff --git a/nestkernel/structural_plasticity_node.cpp b/nestkernel/structural_plasticity_node.cpp index 07a3af88e4..2b04c939d5 100644 --- a/nestkernel/structural_plasticity_node.cpp +++ b/nestkernel/structural_plasticity_node.cpp @@ -25,8 +25,6 @@ // Includes from nestkernel: #include "kernel_manager.h" -// Includes from sli: -#include "dictutils.h" namespace nest { @@ -51,37 +49,35 @@ nest::StructuralPlasticityNode::StructuralPlasticityNode( const StructuralPlasti } void -nest::StructuralPlasticityNode::get_status( DictionaryDatum& d ) const +nest::StructuralPlasticityNode::get_status( Dictionary& d ) const { - DictionaryDatum synaptic_elements_d; - DictionaryDatum synaptic_element_d; - - def< double >( d, names::Ca, Ca_minus_ ); - def< double >( d, names::tau_Ca, tau_Ca_ ); - def< double >( d, names::beta_Ca, beta_Ca_ ); - - synaptic_elements_d = DictionaryDatum( new Dictionary ); - def< DictionaryDatum >( d, names::synaptic_elements, synaptic_elements_d ); - for ( std::map< Name, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); - it != synaptic_elements_map_.end(); - ++it ) + + d[ names::Ca ] = Ca_minus_; + d[ names::tau_Ca ] = tau_Ca_; + d[ names::beta_Ca ] = beta_Ca_; + + Dictionary synaptic_elements_d; + for ( std::map< std::string, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); + it != synaptic_elements_map_.end(); + ++it ) { - synaptic_element_d = DictionaryDatum( new Dictionary ); - def< DictionaryDatum >( synaptic_elements_d, it->first, synaptic_element_d ); + Dictionary synaptic_element_d; it->second.get( synaptic_element_d ); + synaptic_elements_d[ it->first ] = synaptic_element_d; } + d[ names::synaptic_elements ] = synaptic_elements_d; } void -nest::StructuralPlasticityNode::set_status( const DictionaryDatum& d ) +nest::StructuralPlasticityNode::set_status( const Dictionary& d ) { // We need to preserve values in case invalid values are set double new_Ca_ = Ca_minus_; double new_tau_Ca = tau_Ca_; double new_beta_Ca = beta_Ca_; - updateValue< double >( d, names::Ca, new_Ca_ ); - updateValue< double >( d, names::tau_Ca, new_tau_Ca ); - updateValue< double >( d, names::beta_Ca, new_beta_Ca ); + d.update_value( names::Ca, new_Ca_ ); + d.update_value( names::tau_Ca, new_tau_Ca ); + d.update_value( names::beta_Ca, new_beta_Ca ); if ( new_Ca_ < 0.0 ) { @@ -105,42 +101,43 @@ nest::StructuralPlasticityNode::set_status( const DictionaryDatum& d ) // check, if to clear spike history and K_minus bool clear = false; - updateValue< bool >( d, names::clear, clear ); + d.update_value( names::clear, clear ); if ( clear ) { clear_history(); } - if ( d->known( names::synaptic_elements_param ) ) + if ( d.known( names::synaptic_elements_param ) ) { - const DictionaryDatum synaptic_elements_dict = getValue< DictionaryDatum >( d, names::synaptic_elements_param ); + const Dictionary synaptic_elements_dict = d.get< Dictionary >( names::synaptic_elements_param ); - for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); - it != synaptic_elements_map_.end(); - ++it ) + for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + it != synaptic_elements_map_.end(); + ++it ) { - if ( synaptic_elements_dict->known( it->first ) ) + if ( synaptic_elements_dict.known( it->first ) ) { - const DictionaryDatum synaptic_elements_a = getValue< DictionaryDatum >( synaptic_elements_dict, it->first ); + const Dictionary synaptic_elements_a = synaptic_elements_dict.get< Dictionary >( it->first ); it->second.set( synaptic_elements_a ); } } } - if ( not d->known( names::synaptic_elements ) ) + if ( not d.known( names::synaptic_elements ) ) { return; } // we replace the existing synaptic_elements_map_ by the new one - DictionaryDatum synaptic_elements_d; - std::pair< std::map< Name, SynapticElement >::iterator, bool > insert_result; + Dictionary synaptic_elements_d; + std::pair< std::map< std::string, SynapticElement >::iterator, bool > insert_result; - synaptic_elements_map_ = std::map< Name, SynapticElement >(); - synaptic_elements_d = getValue< DictionaryDatum >( d, names::synaptic_elements ); + synaptic_elements_map_ = std::map< std::string, SynapticElement >(); + synaptic_elements_d = d.get< Dictionary >( names::synaptic_elements ); - for ( Dictionary::const_iterator i = synaptic_elements_d->begin(); i != synaptic_elements_d->end(); ++i ) + for ( auto& syn_element : synaptic_elements_d ) { - insert_result = synaptic_elements_map_.insert( std::pair< Name, SynapticElement >( i->first, SynapticElement() ) ); - ( insert_result.first->second ).set( getValue< DictionaryDatum >( synaptic_elements_d, i->first ) ); + SynapticElement se; + se.set( synaptic_elements_d.get< Dictionary >( syn_element.first ) ); + synaptic_elements_map_.insert( std::pair< std::string, SynapticElement >( syn_element.first, se ) ); } } @@ -152,9 +149,9 @@ nest::StructuralPlasticityNode::clear_history() } double -nest::StructuralPlasticityNode::get_synaptic_elements( Name n ) const +nest::StructuralPlasticityNode::get_synaptic_elements( std::string n ) const { - std::map< Name, SynapticElement >::const_iterator se_it; + std::map< std::string, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); double z_value; @@ -177,9 +174,9 @@ nest::StructuralPlasticityNode::get_synaptic_elements( Name n ) const } int -nest::StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const +nest::StructuralPlasticityNode::get_synaptic_elements_vacant( std::string n ) const { - std::map< Name, SynapticElement >::const_iterator se_it; + std::map< std::string, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); if ( se_it != synaptic_elements_map_.end() ) @@ -193,9 +190,9 @@ nest::StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const } int -nest::StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const +nest::StructuralPlasticityNode::get_synaptic_elements_connected( std::string n ) const { - std::map< Name, SynapticElement >::const_iterator se_it; + std::map< std::string, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); if ( se_it != synaptic_elements_map_.end() ) @@ -208,16 +205,16 @@ nest::StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const } } -std::map< Name, double > +std::map< std::string, double > nest::StructuralPlasticityNode::get_synaptic_elements() const { - std::map< Name, double > n_map; + std::map< std::string, double > n_map; - for ( std::map< Name, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); - it != synaptic_elements_map_.end(); - ++it ) + for ( std::map< std::string, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); + it != synaptic_elements_map_.end(); + ++it ) { - n_map.insert( std::pair< Name, double >( it->first, get_synaptic_elements( it->first ) ) ); + n_map.insert( std::pair< std::string, double >( it->first, get_synaptic_elements( it->first ) ) ); } return n_map; } @@ -227,9 +224,9 @@ nest::StructuralPlasticityNode::update_synaptic_elements( double t ) { assert( t >= Ca_t_ ); - for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); - it != synaptic_elements_map_.end(); - ++it ) + for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + it != synaptic_elements_map_.end(); + ++it ) { it->second.update( t, Ca_t_, Ca_minus_, tau_Ca_ ); } @@ -241,18 +238,18 @@ nest::StructuralPlasticityNode::update_synaptic_elements( double t ) void nest::StructuralPlasticityNode::decay_synaptic_elements_vacant() { - for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); - it != synaptic_elements_map_.end(); - ++it ) + for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + it != synaptic_elements_map_.end(); + ++it ) { it->second.decay_z_vacant(); } } void -nest::StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) +nest::StructuralPlasticityNode::connect_synaptic_element( std::string name, int n ) { - std::map< Name, SynapticElement >::iterator se_it; + std::map< std::string, SynapticElement >::iterator se_it; se_it = synaptic_elements_map_.find( name ); if ( se_it != synaptic_elements_map_.end() ) diff --git a/nestkernel/target_table.cpp b/nestkernel/target_table.cpp index d9d06a8c4e..f17375cf2d 100644 --- a/nestkernel/target_table.cpp +++ b/nestkernel/target_table.cpp @@ -71,8 +71,8 @@ void nest::TargetTable::compress_secondary_send_buffer_pos( const size_t tid ) { for ( std::vector< std::vector< std::vector< size_t > > >::iterator it = secondary_send_buffer_pos_[ tid ].begin(); - it != secondary_send_buffer_pos_[ tid ].end(); - ++it ) + it != secondary_send_buffer_pos_[ tid ].end(); + ++it ) { for ( std::vector< std::vector< size_t > >::iterator iit = it->begin(); iit != it->end(); ++iit ) { diff --git a/nestkernel/target_table_devices.cpp b/nestkernel/target_table_devices.cpp index da106e9b43..940695d22b 100644 --- a/nestkernel/target_table_devices.cpp +++ b/nestkernel/target_table_devices.cpp @@ -158,8 +158,8 @@ nest::TargetTableDevices::get_connections_from_devices_( const size_t requested_ std::deque< ConnectionID >& conns ) const { for ( std::vector< size_t >::const_iterator it = sending_devices_node_ids_[ tid ].begin(); - it != sending_devices_node_ids_[ tid ].end(); - ++it ) + it != sending_devices_node_ids_[ tid ].end(); + ++it ) { const size_t source_node_id = *it; if ( source_node_id > 0 and ( requested_source_node_id == source_node_id or requested_source_node_id == 0 ) ) diff --git a/nestkernel/target_table_devices.h b/nestkernel/target_table_devices.h index de6d31db3d..ca147f01cb 100644 --- a/nestkernel/target_table_devices.h +++ b/nestkernel/target_table_devices.h @@ -236,8 +236,8 @@ TargetTableDevices::send_from_device( const size_t tid, const std::vector< ConnectorModel* >& cm ) { for ( std::vector< ConnectorBase* >::iterator it = target_from_devices_[ tid ][ ldid ].begin(); - it != target_from_devices_[ tid ][ ldid ].end(); - ++it ) + it != target_from_devices_[ tid ][ ldid ].end(); + ++it ) { if ( *it ) { diff --git a/nestkernel/target_table_devices_impl.h b/nestkernel/target_table_devices_impl.h index 26a4668fb1..53d052329d 100644 --- a/nestkernel/target_table_devices_impl.h +++ b/nestkernel/target_table_devices_impl.h @@ -80,8 +80,8 @@ nest::TargetTableDevices::send_to_device( const size_t tid, { 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 ) + it != target_to_devices_[ tid ][ lid ].end(); + ++it ) { if ( *it ) { diff --git a/pyproject.toml b/pyproject.toml index 26a94cb932..fbbe90e052 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,3 +14,41 @@ known_third_party = "nest" [tool.black] line-length = 120 + + +[tool.mypy] +# For configuation details see +# +python_version = "3.10" +warn_return_any = true +warn_unused_configs = true +exclude = [ + '.git/', + '.snakemake/', + '.pytest_cache/', + '^sync-test-env/', + '^conda/', + '^env/', + '^doc/htmldoc/developer_space/templates/pynest_example_template\.py$', + # '.*pytests/mpi/./' +] +exclude_gitignore = true +explicit_package_bases = true + +# Check explanations of error codes +# https://mypy.readthedocs.io/en/stable/error_code_list.html +disable_error_code = [ + "attr-defined", + "index", + "import", + "call-arg", + "misc", + "dict-item", + "arg-type", + "operator", + "call-overload", + "assignment", + "list-item", + "var-annotated", + "valid-type", +] diff --git a/requirements_testing.txt b/requirements_testing.txt index c4d4b95fa0..4caeffe599 100644 --- a/requirements_testing.txt +++ b/requirements_testing.txt @@ -21,6 +21,7 @@ pytest-mypy pytest-cov data-science-types terminaltables +pre-commit pycodestyle pydocstyle rstcheck diff --git a/sli/booldatum.cc b/sli/booldatum.cc index 3a70a98e7b..0102f3c12f 100644 --- a/sli/booldatum.cc +++ b/sli/booldatum.cc @@ -35,12 +35,14 @@ BoolDatum::BoolDatum( const Name& val ) d = ( val == Name( true_string ) ); } -BoolDatum::operator Name() const +BoolDatum:: +operator Name() const { return ( d ? Name( true_string ) : Name( false_string ) ); } -BoolDatum::operator std::string() const +BoolDatum:: +operator std::string() const { return ( d ? std::string( true_string ) : std::string( false_string ) ); } diff --git a/sli/token.cc b/sli/token.cc index d565c5de41..63f33268cf 100644 --- a/sli/token.cc +++ b/sli/token.cc @@ -117,27 +117,32 @@ Token::operator Datum* () const } */ -Token::operator long() const +Token:: +operator long() const { return getValue< long >( *this ); } -Token::operator size_t() const +Token:: +operator size_t() const { return getValue< long >( *this ); } -Token::operator double() const +Token:: +operator double() const { return getValue< double >( *this ); } -Token::operator bool() const +Token:: +operator bool() const { return getValue< bool >( *this ); } -Token::operator std::string() const +Token:: +operator std::string() const { return getValue< std::string >( *this ); } diff --git a/testsuite/pytests/mpi/2/connect_test_base.py b/testsuite/pytests/mpi/nproc2/connect_test_base.py similarity index 100% rename from testsuite/pytests/mpi/2/connect_test_base.py rename to testsuite/pytests/mpi/nproc2/connect_test_base.py diff --git a/testsuite/pytests/mpi/2/test_connect_all_to_all.py b/testsuite/pytests/mpi/nproc2/test_connect_all_to_all.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_all_to_all.py rename to testsuite/pytests/mpi/nproc2/test_connect_all_to_all.py diff --git a/testsuite/pytests/mpi/2/test_connect_arrays_mpi.py b/testsuite/pytests/mpi/nproc2/test_connect_arrays_mpi.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_arrays_mpi.py rename to testsuite/pytests/mpi/nproc2/test_connect_arrays_mpi.py diff --git a/testsuite/pytests/mpi/2/test_connect_fixed_indegree.py b/testsuite/pytests/mpi/nproc2/test_connect_fixed_indegree.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_fixed_indegree.py rename to testsuite/pytests/mpi/nproc2/test_connect_fixed_indegree.py diff --git a/testsuite/pytests/mpi/2/test_connect_fixed_outdegree.py b/testsuite/pytests/mpi/nproc2/test_connect_fixed_outdegree.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_fixed_outdegree.py rename to testsuite/pytests/mpi/nproc2/test_connect_fixed_outdegree.py diff --git a/testsuite/pytests/mpi/2/test_connect_fixed_total_number.py b/testsuite/pytests/mpi/nproc2/test_connect_fixed_total_number.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_fixed_total_number.py rename to testsuite/pytests/mpi/nproc2/test_connect_fixed_total_number.py diff --git a/testsuite/pytests/mpi/2/test_connect_one_to_one.py b/testsuite/pytests/mpi/nproc2/test_connect_one_to_one.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_one_to_one.py rename to testsuite/pytests/mpi/nproc2/test_connect_one_to_one.py diff --git a/testsuite/pytests/mpi/2/test_connect_pairwise_bernoulli.py b/testsuite/pytests/mpi/nproc2/test_connect_pairwise_bernoulli.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_pairwise_bernoulli.py rename to testsuite/pytests/mpi/nproc2/test_connect_pairwise_bernoulli.py diff --git a/testsuite/pytests/mpi/2/test_connect_symmetric_pairwise_bernoulli.py b/testsuite/pytests/mpi/nproc2/test_connect_symmetric_pairwise_bernoulli.py similarity index 100% rename from testsuite/pytests/mpi/2/test_connect_symmetric_pairwise_bernoulli.py rename to testsuite/pytests/mpi/nproc2/test_connect_symmetric_pairwise_bernoulli.py diff --git a/testsuite/pytests/mpi/2/test_getnodes.py b/testsuite/pytests/mpi/nproc2/test_getnodes.py similarity index 100% rename from testsuite/pytests/mpi/2/test_getnodes.py rename to testsuite/pytests/mpi/nproc2/test_getnodes.py diff --git a/testsuite/pytests/mpi/2/test_issue_1974.py b/testsuite/pytests/mpi/nproc2/test_issue_1974.py similarity index 100% rename from testsuite/pytests/mpi/2/test_issue_1974.py rename to testsuite/pytests/mpi/nproc2/test_issue_1974.py diff --git a/testsuite/pytests/mpi/2/test_issue_3099.py b/testsuite/pytests/mpi/nproc2/test_issue_3099.py similarity index 100% rename from testsuite/pytests/mpi/2/test_issue_3099.py rename to testsuite/pytests/mpi/nproc2/test_issue_3099.py diff --git a/testsuite/pytests/mpi/2/test_issue_3108.py b/testsuite/pytests/mpi/nproc2/test_issue_3108.py similarity index 100% rename from testsuite/pytests/mpi/2/test_issue_3108.py rename to testsuite/pytests/mpi/nproc2/test_issue_3108.py diff --git a/testsuite/pytests/mpi/2/test_issue_576.py b/testsuite/pytests/mpi/nproc2/test_issue_576.py similarity index 100% rename from testsuite/pytests/mpi/2/test_issue_576.py rename to testsuite/pytests/mpi/nproc2/test_issue_576.py diff --git a/testsuite/pytests/mpi/2/test_multiplicity.py b/testsuite/pytests/mpi/nproc2/test_multiplicity.py similarity index 100% rename from testsuite/pytests/mpi/2/test_multiplicity.py rename to testsuite/pytests/mpi/nproc2/test_multiplicity.py diff --git a/testsuite/pytests/mpi/2/test_neuron_vp.py b/testsuite/pytests/mpi/nproc2/test_neuron_vp.py similarity index 100% rename from testsuite/pytests/mpi/2/test_neuron_vp.py rename to testsuite/pytests/mpi/nproc2/test_neuron_vp.py diff --git a/testsuite/pytests/mpi/2/test_spatial_positions.py b/testsuite/pytests/mpi/nproc2/test_spatial_positions.py similarity index 100% rename from testsuite/pytests/mpi/2/test_spatial_positions.py rename to testsuite/pytests/mpi/nproc2/test_spatial_positions.py diff --git a/testsuite/pytests/mpi/2/test_synapsecollection_mpi.py b/testsuite/pytests/mpi/nproc2/test_synapsecollection_mpi.py similarity index 100% rename from testsuite/pytests/mpi/2/test_synapsecollection_mpi.py rename to testsuite/pytests/mpi/nproc2/test_synapsecollection_mpi.py diff --git a/testsuite/pytests/mpi/3/test_issue_3108.py b/testsuite/pytests/mpi/nproc3/test_issue_3108.py similarity index 100% rename from testsuite/pytests/mpi/3/test_issue_3108.py rename to testsuite/pytests/mpi/nproc3/test_issue_3108.py diff --git a/testsuite/pytests/mpi/3/test_neuron_vp.py b/testsuite/pytests/mpi/nproc3/test_neuron_vp.py similarity index 100% rename from testsuite/pytests/mpi/3/test_neuron_vp.py rename to testsuite/pytests/mpi/nproc3/test_neuron_vp.py diff --git a/testsuite/pytests/mpi/4/test_consistent_local_vps.py b/testsuite/pytests/mpi/nproc4/test_consistent_local_vps.py similarity index 100% rename from testsuite/pytests/mpi/4/test_consistent_local_vps.py rename to testsuite/pytests/mpi/nproc4/test_consistent_local_vps.py diff --git a/testsuite/pytests/mpi/4/test_delay_exchange.py b/testsuite/pytests/mpi/nproc4/test_delay_exchange.py similarity index 100% rename from testsuite/pytests/mpi/4/test_delay_exchange.py rename to testsuite/pytests/mpi/nproc4/test_delay_exchange.py diff --git a/testsuite/pytests/mpi/4/test_getnodes.py b/testsuite/pytests/mpi/nproc4/test_getnodes.py similarity index 100% rename from testsuite/pytests/mpi/4/test_getnodes.py rename to testsuite/pytests/mpi/nproc4/test_getnodes.py diff --git a/testsuite/pytests/mpi/4/test_issue_1974.py b/testsuite/pytests/mpi/nproc4/test_issue_1974.py similarity index 100% rename from testsuite/pytests/mpi/4/test_issue_1974.py rename to testsuite/pytests/mpi/nproc4/test_issue_1974.py diff --git a/testsuite/pytests/mpi/4/test_issue_3108.py b/testsuite/pytests/mpi/nproc4/test_issue_3108.py similarity index 100% rename from testsuite/pytests/mpi/4/test_issue_3108.py rename to testsuite/pytests/mpi/nproc4/test_issue_3108.py diff --git a/testsuite/pytests/mpi/4/test_localonly.py b/testsuite/pytests/mpi/nproc4/test_localonly.py similarity index 100% rename from testsuite/pytests/mpi/4/test_localonly.py rename to testsuite/pytests/mpi/nproc4/test_localonly.py diff --git a/testsuite/pytests/mpi/4/test_set_status_resolution_nthreads.py b/testsuite/pytests/mpi/nproc4/test_set_status_resolution_nthreads.py similarity index 100% rename from testsuite/pytests/mpi/4/test_set_status_resolution_nthreads.py rename to testsuite/pytests/mpi/nproc4/test_set_status_resolution_nthreads.py diff --git a/testsuite/pytests/mpi/4/test_spatial_positions.py b/testsuite/pytests/mpi/nproc4/test_spatial_positions.py similarity index 100% rename from testsuite/pytests/mpi/4/test_spatial_positions.py rename to testsuite/pytests/mpi/nproc4/test_spatial_positions.py diff --git a/testsuite/pytests/mpi/4/test_spike_train_injector_mpi.py b/testsuite/pytests/mpi/nproc4/test_spike_train_injector_mpi.py similarity index 100% rename from testsuite/pytests/mpi/4/test_spike_train_injector_mpi.py rename to testsuite/pytests/mpi/nproc4/test_spike_train_injector_mpi.py diff --git a/testsuite/pytests/sli2py_regressions/test_ticket_638.py b/testsuite/pytests/sli2py_regressions/test_ticket_638.py index fc26de9859..afd803db95 100644 --- a/testsuite/pytests/sli2py_regressions/test_ticket_638.py +++ b/testsuite/pytests/sli2py_regressions/test_ticket_638.py @@ -43,7 +43,7 @@ def _run_simulation(model: str, t_ref: float) -> int: nest.Connect(neuron, spike_recorder) nest.Simulate(100.0) - n_events = spike_recorder.get("n_events") + n_events: int = spike_recorder.get("n_events") return n_events diff --git a/testsuite/pytests/sli2py_regressions/test_ticket_673.py b/testsuite/pytests/sli2py_regressions/test_ticket_673.py index 29c9843c31..9beff56370 100644 --- a/testsuite/pytests/sli2py_regressions/test_ticket_673.py +++ b/testsuite/pytests/sli2py_regressions/test_ticket_673.py @@ -46,7 +46,7 @@ def _second_spike_time(model: str, t_ref: float) -> float: nest.Simulate(20.0) events = nest.GetStatus(spike_recorder, "events")[0] - times = events["times"] + times: list[float] = events["times"] assert len(times) > 1, f"Model {model} did not fire at least twice." diff --git a/testsuite/pytests/test_connect_all_to_all.py b/testsuite/pytests/test_connect_all_to_all.py index cb473cdb0e..38b78cfdd4 100644 --- a/testsuite/pytests/test_connect_all_to_all.py +++ b/testsuite/pytests/test_connect_all_to_all.py @@ -22,11 +22,12 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_MPI = nest.ll_api.sli_func("statusdict/have_mpi ::") HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_indegree.py b/testsuite/pytests/test_connect_fixed_indegree.py index 9324f27dc3..964dce6e7c 100644 --- a/testsuite/pytests/test_connect_fixed_indegree.py +++ b/testsuite/pytests/test_connect_fixed_indegree.py @@ -22,11 +22,12 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_outdegree.py b/testsuite/pytests/test_connect_fixed_outdegree.py index 01240a58d3..78089bef9c 100644 --- a/testsuite/pytests/test_connect_fixed_outdegree.py +++ b/testsuite/pytests/test_connect_fixed_outdegree.py @@ -21,11 +21,12 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_total_number.py b/testsuite/pytests/test_connect_fixed_total_number.py index d56ade993d..0e2cafdd82 100644 --- a/testsuite/pytests/test_connect_fixed_total_number.py +++ b/testsuite/pytests/test_connect_fixed_total_number.py @@ -21,11 +21,12 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_one_to_one.py b/testsuite/pytests/test_connect_one_to_one.py index 7bcce2f8f4..5f3175f72a 100644 --- a/testsuite/pytests/test_connect_one_to_one.py +++ b/testsuite/pytests/test_connect_one_to_one.py @@ -21,10 +21,11 @@ import unittest -import connect_test_base import nest import numpy as np +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_pairwise_bernoulli.py b/testsuite/pytests/test_connect_pairwise_bernoulli.py index cb8e2a110e..576fcd419e 100644 --- a/testsuite/pytests/test_connect_pairwise_bernoulli.py +++ b/testsuite/pytests/test_connect_pairwise_bernoulli.py @@ -22,11 +22,12 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_pairwise_poisson.py b/testsuite/pytests/test_connect_pairwise_poisson.py index f7a2c693ca..0270bcef77 100644 --- a/testsuite/pytests/test_connect_pairwise_poisson.py +++ b/testsuite/pytests/test_connect_pairwise_poisson.py @@ -22,12 +22,13 @@ import unittest -import connect_test_base import nest import numpy as np import scipy.stats from connect_test_base import get_connectivity_matrix +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py b/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py index f7c663fe7d..335f1adb2b 100644 --- a/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py +++ b/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py @@ -23,11 +23,12 @@ import collections import unittest -import connect_test_base import nest import numpy as np import scipy.stats +from . import connect_test_base + HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/regressiontests/issue-1703.py b/testsuite/regressiontests/issue-1703.py index 3031fc70cb..45a5dd76f4 100644 --- a/testsuite/regressiontests/issue-1703.py +++ b/testsuite/regressiontests/issue-1703.py @@ -20,8 +20,8 @@ # along with NEST. If not, see . """ -This script ensures that importing NEST after mpi4py does not lead -to a segmentation fault when simulating. +Ensures that importing NEST after mpi4py does not lead to a segmentation fault +when simulating. This is a regression test for GitHub issue 1703. """ diff --git a/testsuite/regressiontests/sli2py_ignore/issue-779-1016.py b/testsuite/regressiontests/sli2py_ignore/issue-779-1016.py index e182bc8cdd..81f6f1f426 100644 --- a/testsuite/regressiontests/sli2py_ignore/issue-779-1016.py +++ b/testsuite/regressiontests/sli2py_ignore/issue-779-1016.py @@ -20,8 +20,8 @@ # along with NEST. If not, see . """ -This script ensures that NEST parses commandline arguments correctly -and makes all of them available in the argv array in the statusdict. +Ensures that NEST parses commandline arguments correctly and makes all of them +available in the argv array in the statusdict. This is a regression test for GitHub issues 779 and 1016. """ diff --git a/testsuite/run_test.sh b/testsuite/run_test.sh index 4cb3f96d0f..e7dab63089 100755 --- a/testsuite/run_test.sh +++ b/testsuite/run_test.sh @@ -156,7 +156,7 @@ run_test () echo "${explanation}" - if test "x${msg_error}" != x ; then + if test -n "${msg_error}"; then echo ================================================== echo "Following is the full output of the test:" echo ================================================== @@ -170,7 +170,7 @@ run_test () junit_write "${junit_class}" "${junit_name}" "${junit_status}" "${junit_failure}" "$(cat "${TEST_OUTFILE}")" # Panic on "unexpected" exit code - if test "x${unexpected_exitcode:-}" != x ; then + if test -n "${unexpected_exitcode:-}"; then echo "***" echo "*** An unexpected exit code usually hints at a bug in the test suite!" exit 2 diff --git a/testsuite/summarize_tests.py b/testsuite/summarize_tests.py index 5f084c05c7..bacd21e97f 100644 --- a/testsuite/summarize_tests.py +++ b/testsuite/summarize_tests.py @@ -49,9 +49,9 @@ "05 mpitests": 1, # set to 1 to avoid complications during porting to Pytest "06 musictests": 1, "07 pynesttests": 3719, # without thread-dependent cases - "07 pynesttests mpi 2": (230, 172), # first case without thread-dependent cases - "07 pynesttests mpi 3": (58, 0), - "07 pynesttests mpi 4": (65, 7), + "07 pynesttests mpi nproc2": (230, 172), # first case without thread-dependent cases + "07 pynesttests mpi nproc3": (58, 0), + "07 pynesttests mpi nproc4": (65, 7), "07 pynesttests sli2py mpi": 13, "08 cpptests": 29, } From 0d9cf7ba50fc23670715894f53a542d1cda1dce0 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 12:16:27 +0100 Subject: [PATCH 02/10] remove dead config line --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fbbe90e052..f9b4efabaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,6 @@ exclude = [ '^conda/', '^env/', '^doc/htmldoc/developer_space/templates/pynest_example_template\.py$', - # '.*pytests/mpi/./' ] exclude_gitignore = true explicit_package_bases = true From e8982c94a151722da119f45dbcbae718da29382e Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 12:27:12 +0100 Subject: [PATCH 03/10] revert changes that leaked in from pynestng --- nestkernel/conn_builder.cpp | 380 +++++++++++----------- nestkernel/connection_creator.cpp | 112 +++---- nestkernel/kernel_manager.cpp | 218 +------------ nestkernel/spatial.cpp | 268 ++++----------- nestkernel/structural_plasticity_node.cpp | 87 ++--- 5 files changed, 382 insertions(+), 683 deletions(-) diff --git a/nestkernel/conn_builder.cpp b/nestkernel/conn_builder.cpp index 380e1f323f..968a75c031 100644 --- a/nestkernel/conn_builder.cpp +++ b/nestkernel/conn_builder.cpp @@ -35,6 +35,11 @@ #include "node.h" #include "vp_manager_impl.h" +// Includes from sli: +#include "dict.h" +#include "fdstream.h" +#include "name.h" + // Includes from C++: #include @@ -42,8 +47,8 @@ nest::ConnBuilder::ConnBuilder( const std::string& primary_rule, NodeCollectionPTR sources, NodeCollectionPTR targets, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : third_in_builder_( nullptr ) , third_out_builder_( nullptr ) , primary_builder_( kernel().connection_manager.get_conn_builder( primary_rule, @@ -60,26 +65,26 @@ nest::ConnBuilder::ConnBuilder( const std::string& primary_rule, NodeCollectionPTR sources, NodeCollectionPTR targets, NodeCollectionPTR third, - const Dictionary& conn_spec, - const Dictionary& third_conn_spec, - const std::map< std::string, std::vector< Dictionary > >& syn_specs ) + const DictionaryDatum& conn_spec, + const DictionaryDatum& third_conn_spec, + const std::map< Name, std::vector< DictionaryDatum > >& syn_specs ) : third_in_builder_( new ThirdInBuilder( sources, third, third_conn_spec, - const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::third_in ] ) ) + const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::third_in ] ) ) , third_out_builder_( kernel().connection_manager.get_third_conn_builder( third_rule, third, targets, third_in_builder_, third_conn_spec, // const_cast here seems required, clang complains otherwise; try to clean up when Datums disappear - const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::third_out ] ) ) + const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::third_out ] ) ) , primary_builder_( kernel().connection_manager.get_conn_builder( primary_rule, sources, targets, third_out_builder_, conn_spec, - const_cast< std::map< std::string, std::vector< Dictionary > >& >( syn_specs )[ names::primary ] ) ) + const_cast< std::map< Name, std::vector< DictionaryDatum > >& >( syn_specs )[ names::primary ] ) ) { } @@ -114,8 +119,8 @@ nest::ConnBuilder::disconnect() nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : sources_( sources ) , targets_( targets ) , third_out_( third_out ) @@ -131,9 +136,9 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, // We only read a subset of rule-related parameters here. The property 'rule' // has already been taken care of in ConnectionManager::get_conn_builder() and // rule-specific parameters are handled by the subclass constructors. - conn_spec.update_value< bool >( names::allow_autapses, allow_autapses_ ); - conn_spec.update_value< bool >( names::allow_multapses, allow_multapses_ ); - conn_spec.update_value< bool >( names::make_symmetric, make_symmetric_ ); + updateValue< bool >( conn_spec, names::allow_autapses, allow_autapses_ ); + updateValue< bool >( conn_spec, names::allow_multapses, allow_multapses_ ); + updateValue< bool >( conn_spec, names::make_symmetric, make_symmetric_ ); if ( make_symmetric_ and third_out_ ) { @@ -152,21 +157,22 @@ nest::BipartiteConnBuilder::BipartiteConnBuilder( NodeCollectionPTR sources, delays_.resize( syn_specs.size() ); synapse_params_.resize( syn_specs.size() ); synapse_model_id_.resize( syn_specs.size() ); + synapse_model_id_[ 0 ] = kernel().model_manager.get_synapse_model_id( "static_synapse" ); param_dicts_.resize( syn_specs.size() ); // loop through vector of synapse dictionaries, and set synapse parameters for ( size_t synapse_indx = 0; synapse_indx < syn_specs.size(); ++synapse_indx ) { - auto& syn_params = syn_specs[ synapse_indx ]; + auto syn_params = syn_specs[ synapse_indx ]; set_synapse_model_( syn_params, synapse_indx ); set_default_weight_or_delay_( syn_params, synapse_indx ); - Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); + DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); #ifdef HAVE_MUSIC // We allow music_channel as alias for receptor_type during connection setup - syn_defaults[ names::music_channel ] = 0; + ( *syn_defaults )[ names::music_channel ] = 0; #endif set_synapse_params( syn_defaults, syn_params, synapse_indx ); @@ -320,11 +326,11 @@ nest::BipartiteConnBuilder::connect() } } // check if any exceptions have been raised - for ( auto eptr : exceptions_raised_ ) + for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { - if ( eptr ) + if ( exceptions_raised_.at( tid ).get() ) { - std::rethrow_exception( eptr ); + throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); } } } @@ -342,11 +348,11 @@ nest::BipartiteConnBuilder::disconnect() } // check if any exceptions have been raised - for ( auto eptr : exceptions_raised_ ) + for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { - if ( eptr ) + if ( exceptions_raised_.at( tid ).get() ) { - std::rethrow_exception( eptr ); + throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); } } } @@ -364,13 +370,17 @@ nest::BipartiteConnBuilder::update_param_dict_( size_t snode_id, { if ( synapse_parameter.second->provides_long() ) { - param_dicts_[ synapse_indx ][ target_thread ][ synapse_parameter.first ] = - synapse_parameter.second->value_int( target_thread, rng, snode_id, &target ); + // change value of dictionary entry without allocating new datum + IntegerDatum* id = static_cast< IntegerDatum* >( + ( ( *param_dicts_[ synapse_indx ][ target_thread ] )[ synapse_parameter.first ] ).datum() ); + ( *id ) = synapse_parameter.second->value_int( target_thread, rng, snode_id, &target ); } else { - param_dicts_[ synapse_indx ][ target_thread ][ synapse_parameter.first ] = - synapse_parameter.second->value_double( target_thread, rng, snode_id, &target ); + // change value of dictionary entry without allocating new datum + DoubleDatum* dd = static_cast< DoubleDatum* >( + ( ( *param_dicts_[ synapse_indx ][ target_thread ] )[ synapse_parameter.first ] ).datum() ); + ( *dd ) = synapse_parameter.second->value_double( target_thread, rng, snode_id, &target ); } } } @@ -489,11 +499,13 @@ nest::BipartiteConnBuilder::loop_over_targets_() const } void -nest::BipartiteConnBuilder::set_synapse_model_( const Dictionary& syn_params, size_t synapse_indx ) +nest::BipartiteConnBuilder::set_synapse_model_( DictionaryDatum syn_params, size_t synapse_indx ) { - const std::string syn_name = syn_params.known( names::synapse_model ) - ? syn_params.get< std::string >( names::synapse_model ) - : std::string( "static_synapse" ); + if ( not syn_params->known( names::synapse_model ) ) + { + throw BadProperty( "Synapse spec must contain synapse model." ); + } + const std::string syn_name = ( *syn_params )[ names::synapse_model ]; // The following call will throw "UnknownSynapseType" if syn_name is not naming a known model const size_t synapse_model_id = kernel().model_manager.get_synapse_model_id( syn_name ); @@ -505,14 +517,15 @@ nest::BipartiteConnBuilder::set_synapse_model_( const Dictionary& syn_params, si } void -nest::BipartiteConnBuilder::set_default_weight_or_delay_( const Dictionary& syn_params, size_t synapse_indx ) +nest::BipartiteConnBuilder::set_default_weight_or_delay_( DictionaryDatum syn_params, size_t synapse_indx ) { - Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); + DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id_[ synapse_indx ] ); // All synapse models have the possibility to set the delay (see SynIdDelay), but some have // homogeneous weights, hence it should be possible to set the delay without the weight. - default_weight_[ synapse_indx ] = not syn_params.known( names::weight ); - default_delay_[ synapse_indx ] = not syn_params.known( names::delay ); + default_weight_[ synapse_indx ] = not syn_params->known( names::weight ); + + default_delay_[ synapse_indx ] = not syn_params->known( names::delay ); // If neither weight nor delay are given in the dict, we handle this separately. Important for // hom_w synapses, on which weight cannot be set. However, we use default weight and delay for @@ -521,40 +534,41 @@ nest::BipartiteConnBuilder::set_default_weight_or_delay_( const Dictionary& syn_ if ( not default_weight_and_delay_[ synapse_indx ] ) { - weights_[ synapse_indx ] = syn_params.known( names::weight ) - ? ConnParameter::create( syn_params.at( names::weight ), kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( syn_defaults[ names::weight ], kernel().vp_manager.get_num_threads() ); + weights_[ synapse_indx ] = syn_params->known( names::weight ) + ? ConnParameter::create( ( *syn_params )[ names::weight ], kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( ( *syn_defaults )[ names::weight ], kernel().vp_manager.get_num_threads() ); register_parameters_requiring_skipping_( *weights_[ synapse_indx ] ); - delays_[ synapse_indx ] = syn_params.known( names::delay ) - ? ConnParameter::create( syn_params.at( names::delay ), kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( syn_defaults[ names::delay ], kernel().vp_manager.get_num_threads() ); + delays_[ synapse_indx ] = syn_params->known( names::delay ) + ? ConnParameter::create( ( *syn_params )[ names::delay ], kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( ( *syn_defaults )[ names::delay ], kernel().vp_manager.get_num_threads() ); } else if ( default_weight_[ synapse_indx ] ) { - delays_[ synapse_indx ] = syn_params.known( names::delay ) - ? ConnParameter::create( syn_params.at( names::delay ), kernel().vp_manager.get_num_threads() ) - : ConnParameter::create( syn_defaults[ names::delay ], kernel().vp_manager.get_num_threads() ); + delays_[ synapse_indx ] = syn_params->known( names::delay ) + ? ConnParameter::create( ( *syn_params )[ names::delay ], kernel().vp_manager.get_num_threads() ) + : ConnParameter::create( ( *syn_defaults )[ names::delay ], kernel().vp_manager.get_num_threads() ); } register_parameters_requiring_skipping_( *delays_[ synapse_indx ] ); } void -nest::BipartiteConnBuilder::set_synapse_params( const Dictionary& syn_defaults, - const Dictionary& syn_params, +nest::BipartiteConnBuilder::set_synapse_params( DictionaryDatum syn_defaults, + DictionaryDatum syn_params, size_t synapse_indx ) { - for ( [[maybe_unused]] const auto& [ param_name, unused ] : syn_defaults ) + for ( Dictionary::const_iterator default_it = syn_defaults->begin(); default_it != syn_defaults->end(); ++default_it ) { + const Name param_name = default_it->first; if ( skip_syn_params_.find( param_name ) != skip_syn_params_.end() ) { continue; // weight, delay or other not-settable parameter } - if ( syn_params.known( param_name ) ) + if ( syn_params->known( param_name ) ) { synapse_params_[ synapse_indx ][ param_name ] = - ConnParameter::create( syn_params.at( param_name ), kernel().vp_manager.get_num_threads() ); + ConnParameter::create( ( *syn_params )[ param_name ], kernel().vp_manager.get_num_threads() ); register_parameters_requiring_skipping_( *synapse_params_[ synapse_indx ][ param_name ] ); } } @@ -563,59 +577,52 @@ nest::BipartiteConnBuilder::set_synapse_params( const Dictionary& syn_defaults, // create it here once to avoid re-creating the object over and over again. for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { - param_dicts_[ synapse_indx ].emplace_back(); + param_dicts_[ synapse_indx ].push_back( new Dictionary() ); for ( auto param : synapse_params_[ synapse_indx ] ) { if ( param.second->provides_long() ) { - param_dicts_[ synapse_indx ][ tid ][ param.first ] = 0; + ( *param_dicts_[ synapse_indx ][ tid ] )[ param.first ] = Token( new IntegerDatum( 0 ) ); } else { - param_dicts_[ synapse_indx ][ tid ][ param.first ] = 0.0; + ( *param_dicts_[ synapse_indx ][ tid ] )[ param.first ] = Token( new DoubleDatum( 0.0 ) ); } } } } void -nest::BipartiteConnBuilder::set_structural_plasticity_parameters( const std::vector< Dictionary >& syn_specs ) +nest::BipartiteConnBuilder::set_structural_plasticity_parameters( std::vector< DictionaryDatum > syn_specs ) { - // We must check here if any syn_spec provided contains sp-related parameters bool have_structural_plasticity_parameters = false; for ( auto& syn_spec : syn_specs ) { - if ( syn_spec.known( names::pre_synaptic_element ) or syn_spec.known( names::post_synaptic_element ) ) + if ( syn_spec->known( names::pre_synaptic_element ) or syn_spec->known( names::post_synaptic_element ) ) { have_structural_plasticity_parameters = true; } } + if ( not have_structural_plasticity_parameters ) { return; } - // We now know that we have SP-parameters and can perform SP-specific checks and operations if ( syn_specs.size() > 1 ) { throw KernelException( "Structural plasticity can only be used with a single syn_spec." ); } - // We know now that we only have a single syn spec and work with that in what follows. - // We take a reference to avoid copying. This also ensures that access to the dictionary - // elements is properly registered in the actual dictionary passed in from the Python level. - const Dictionary& syn_spec = syn_specs[ 0 ]; - - // != is the correct way to express exclusive or in C ++."xor" is bitwise. - if ( syn_spec.known( names::pre_synaptic_element ) != syn_spec.known( names::post_synaptic_element ) ) + const DictionaryDatum syn_spec = syn_specs[ 0 ]; + if ( syn_spec->known( names::pre_synaptic_element ) xor syn_spec->known( names::post_synaptic_element ) ) { throw BadProperty( "Structural plasticity requires both a pre- and postsynaptic element." ); } - pre_synaptic_element_name_ = syn_spec.get< std::string >( names::pre_synaptic_element ); - post_synaptic_element_name_ = syn_spec.get< std::string >( names::post_synaptic_element ); - + pre_synaptic_element_name_ = getValue< std::string >( syn_spec, names::pre_synaptic_element ); + post_synaptic_element_name_ = getValue< std::string >( syn_spec, names::post_synaptic_element ); use_structural_plasticity_ = true; } @@ -645,8 +652,8 @@ nest::BipartiteConnBuilder::reset_delays_() nest::ThirdInBuilder::ThirdInBuilder( NodeCollectionPTR sources, NodeCollectionPTR third, - const Dictionary& third_conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& third_conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, third, nullptr, third_conn_spec, syn_specs ) , source_third_gids_( kernel().vp_manager.get_num_threads(), nullptr ) , source_third_counts_( kernel().vp_manager.get_num_threads(), nullptr ) @@ -775,8 +782,8 @@ nest::ThirdInBuilder::connect_() nest::ThirdOutBuilder::ThirdOutBuilder( const NodeCollectionPTR third, const NodeCollectionPTR targets, ThirdInBuilder* third_in, - const Dictionary& third_conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& third_conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( third, targets, nullptr, third_conn_spec, syn_specs ) , third_in_( third_in ) { @@ -785,8 +792,8 @@ nest::ThirdOutBuilder::ThirdOutBuilder( const NodeCollectionPTR third, nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCollectionPTR third, const NodeCollectionPTR targets, ThirdInBuilder* third_in, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : ThirdOutBuilder( third, targets, third_in, conn_spec, syn_specs ) , p_( 1.0 ) , random_pool_( true ) @@ -794,19 +801,10 @@ nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCo , targets_per_third_( targets->size() / third->size() ) , pools_( kernel().vp_manager.get_num_threads(), nullptr ) { - conn_spec.update_value( names::p, p_ ); - - // PYTEST-NG: Consider cleaner scheme for handling size_t vs long - long pool_size_tmp = static_cast< long >( pool_size_ ); - conn_spec.update_value( names::pool_size, pool_size_tmp ); - if ( pool_size_tmp < 1 or third->size() < pool_size_tmp ) - { - throw BadProperty( "Pool size 1 ≤ pool_size ≤ size of third-factor population required" ); - } - pool_size_ = static_cast< size_t >( pool_size_tmp ); - + updateValue< double >( conn_spec, names::p, p_ ); + updateValue< long >( conn_spec, names::pool_size, pool_size_ ); std::string pool_type; - if ( conn_spec.update_value( names::pool_type, pool_type ) ) + if ( updateValue< std::string >( conn_spec, names::pool_type, pool_type ) ) { if ( pool_type == "random" ) { @@ -827,6 +825,11 @@ nest::ThirdBernoulliWithPoolBuilder::ThirdBernoulliWithPoolBuilder( const NodeCo throw BadProperty( "Conditional probability of third-factor connection 0 ≤ p_third_if_primary ≤ 1 required" ); } + if ( pool_size_ < 1 or third->size() < pool_size_ ) + { + throw BadProperty( "Pool size 1 ≤ pool_size ≤ size of third-factor population required" ); + } + if ( not( random_pool_ or ( targets->size() * pool_size_ == third->size() ) or ( pool_size_ == 1 and targets->size() % third->size() == 0 ) ) ) { @@ -945,8 +948,8 @@ nest::ThirdBernoulliWithPoolBuilder::get_first_pool_index_( const size_t target_ nest::OneToOneBuilder::OneToOneBuilder( const NodeCollectionPTR sources, const NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // make sure that target and source population have the same size @@ -1026,10 +1029,11 @@ nest::OneToOneBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1073,10 +1077,11 @@ nest::OneToOneBuilder::disconnect_() single_disconnect_( snode_id, *target, target_thread ); } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1119,10 +1124,11 @@ nest::OneToOneBuilder::sp_connect_() single_connect_( snode_id, *target, target_thread, rng ); } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1158,10 +1164,11 @@ nest::OneToOneBuilder::sp_disconnect_() single_disconnect_( snode_id, *target, target_thread ); } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1213,10 +1220,11 @@ nest::AllToAllBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1291,10 +1299,11 @@ nest::AllToAllBuilder::sp_connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1340,10 +1349,11 @@ nest::AllToAllBuilder::disconnect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1379,10 +1389,11 @@ nest::AllToAllBuilder::sp_disconnect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1390,27 +1401,27 @@ nest::AllToAllBuilder::sp_disconnect_() nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // check for potential errors - const size_t n_sources = sources_->size(); + long n_sources = static_cast< long >( sources_->size() ); if ( n_sources == 0 ) { throw BadProperty( "Source array must not be empty." ); } - auto indegree = conn_spec.at( names::indegree ); - if ( is_type< std::shared_ptr< nest::Parameter > >( indegree ) ) + ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::indegree ].datum() ); + if ( pd ) { - indegree_ = boost::any_cast< ParameterPTR >( indegree ); + indegree_ = *pd; // TODO: Checks of parameter range } else { // Assume indegree is a scalar - const long value = conn_spec.get< long >( names::indegree ); - indegree_ = ParameterPTR( new ConstantParameter( value ) ); + const long value = ( *conn_spec )[ names::indegree ]; + indegree_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); // verify that indegree is not larger than source population if multapses are disabled if ( not allow_multapses_ ) @@ -1421,7 +1432,7 @@ nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, } else if ( value == n_sources and not allow_autapses_ ) { - LOG( VerbosityLevel::WARNING, + LOG( M_WARNING, "FixedInDegreeBuilder::connect", "Multapses and autapses prohibited. When the sources and the targets " "have a non-empty intersection, the connect algorithm will enter an infinite loop." ); @@ -1430,7 +1441,7 @@ nest::FixedInDegreeBuilder::FixedInDegreeBuilder( NodeCollectionPTR sources, if ( value > 0.9 * n_sources ) { - LOG( VerbosityLevel::WARNING, + LOG( M_WARNING, "FixedInDegreeBuilder::connect", "Multapses are prohibited and you request more than 90% connectivity. Expect long connecting times!" ); } @@ -1495,10 +1506,11 @@ nest::FixedInDegreeBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1554,8 +1566,8 @@ nest::FixedInDegreeBuilder::inner_connect_( const int tid, nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // check for potential errors @@ -1564,17 +1576,18 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, { throw BadProperty( "Target array must not be empty." ); } - auto outdegree = conn_spec.at( names::outdegree ); - if ( is_type< std::shared_ptr< nest::Parameter > >( outdegree ) ) + ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::outdegree ].datum() ); + if ( pd ) { - outdegree_ = boost::any_cast< ParameterPTR >( outdegree ); + outdegree_ = *pd; // TODO: Checks of parameter range } else { // Assume outdegree is a scalar - const long value = conn_spec.get< long >( names::outdegree ); - outdegree_ = ParameterPTR( new ConstantParameter( value ) ); + const long value = ( *conn_spec )[ names::outdegree ]; + + outdegree_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); // verify that outdegree is not larger than target population if multapses // are disabled @@ -1586,7 +1599,7 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, } else if ( value == n_targets and not allow_autapses_ ) { - LOG( VerbosityLevel::WARNING, + LOG( M_WARNING, "FixedOutDegreeBuilder::connect", "Multapses and autapses prohibited. When the sources and the targets " "have a non-empty intersection, the connect algorithm will enter an infinite loop." ); @@ -1595,7 +1608,7 @@ nest::FixedOutDegreeBuilder::FixedOutDegreeBuilder( NodeCollectionPTR sources, if ( value > 0.9 * n_targets ) { - LOG( VerbosityLevel::WARNING, + LOG( M_WARNING, "FixedOutDegreeBuilder::connect", "Multapses are prohibited and you request more than 90% connectivity. Expect long connecting times!" ); } @@ -1671,10 +1684,11 @@ nest::FixedOutDegreeBuilder::connect_() single_connect_( snode_id, *target, tid, rng ); } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1683,10 +1697,10 @@ nest::FixedOutDegreeBuilder::connect_() nest::FixedTotalNumberBuilder::FixedTotalNumberBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) - , N_( conn_spec.get< long >( names::N ) ) + , N_( ( *conn_spec )[ names::N ] ) { // check for potential errors @@ -1841,10 +1855,11 @@ nest::FixedTotalNumberBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -1853,25 +1868,25 @@ nest::FixedTotalNumberBuilder::connect_() nest::BernoulliBuilder::BernoulliBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { - auto p = conn_spec.at( names::p ); - if ( is_type< std::shared_ptr< nest::Parameter > >( p ) ) + ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::p ].datum() ); + if ( pd ) { - p_ = boost::any_cast< ParameterPTR >( p ); + p_ = *pd; // TODO: Checks of parameter range } else { // Assume p is a scalar - const double value = conn_spec.get< double >( names::p ); + const double value = ( *conn_spec )[ names::p ]; if ( value < 0 or 1 < value ) { throw BadProperty( "Connection probability 0 <= p <= 1 required." ); } - p_ = ParameterPTR( new ConstantParameter( value ) ); + p_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); } } @@ -1924,10 +1939,11 @@ nest::BernoulliBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } // of omp parallel } @@ -1968,30 +1984,28 @@ nest::BernoulliBuilder::inner_connect_( const int tid, RngPtr rng, Node* target, nest::PoissonBuilder::PoissonBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { - - auto p = conn_spec.at( names::pairwise_avg_num_conns ); - if ( is_type< std::shared_ptr< nest::Parameter > >( p ) ) + ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *conn_spec )[ names::pairwise_avg_num_conns ].datum() ); + if ( pd ) { - pairwise_avg_num_conns_ = boost::any_cast< ParameterPTR >( p ); + pairwise_avg_num_conns_ = *pd; } else { // Assume pairwise_avg_num_conns is a scalar - const double value = conn_spec.get< double >( names::pairwise_avg_num_conns ); + const double value = ( *conn_spec )[ names::pairwise_avg_num_conns ]; if ( value < 0 ) { throw BadProperty( "Connection parameter 0 ≤ pairwise_avg_num_conns required." ); } - pairwise_avg_num_conns_ = ParameterPTR( new ConstantParameter( value ) ); - } - - if ( not allow_multapses_ ) - { - throw BadProperty( "Multapses must be allowed for this connection rule." ); + if ( not allow_multapses_ ) + { + throw BadProperty( "Multapses must be allowed for this connection rule." ); + } + pairwise_avg_num_conns_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); } } @@ -2041,9 +2055,11 @@ nest::PoissonBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } // of omp parallel } @@ -2086,10 +2102,10 @@ nest::PoissonBuilder::inner_connect_( const int tid, RngPtr rng, Node* target, s nest::SymmetricBernoulliBuilder::SymmetricBernoulliBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) - , p_( conn_spec.get< double >( names::p ) ) + , p_( ( *conn_spec )[ names::p ] ) { // This connector takes care of symmetric connections on its own creates_symmetric_connections_ = true; @@ -2201,10 +2217,11 @@ nest::SymmetricBernoulliBuilder::connect_() } } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } @@ -2213,8 +2230,8 @@ nest::SymmetricBernoulliBuilder::connect_() nest::SPBuilder::SPBuilder( NodeCollectionPTR sources, NodeCollectionPTR targets, ThirdOutBuilder* third_out, - const Dictionary& conn_spec, - const std::vector< Dictionary >& syn_specs ) + const DictionaryDatum& conn_spec, + const std::vector< DictionaryDatum >& syn_specs ) : BipartiteConnBuilder( sources, targets, third_out, conn_spec, syn_specs ) { // Check that both pre and postsynaptic element are provided @@ -2229,8 +2246,8 @@ nest::SPBuilder::update_delay( long& d ) const { if ( get_default_delay() ) { - Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( get_synapse_model() ); - const double delay = syn_defaults.get< double >( "delay" ); + DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( get_synapse_model() ); + const double delay = getValue< double >( syn_defaults, "delay" ); d = Time( Time::ms( delay ) ).get_steps(); } } @@ -2241,11 +2258,11 @@ nest::SPBuilder::sp_connect( const std::vector< size_t >& sources, const std::ve connect_( sources, targets ); // check if any exceptions have been raised - for ( auto eptr : exceptions_raised_ ) + for ( size_t tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid ) { - if ( eptr ) + if ( exceptions_raised_.at( tid ).get() ) { - std::rethrow_exception( eptr ); + throw WrappedThreadException( *( exceptions_raised_.at( tid ) ) ); } } } @@ -2305,10 +2322,11 @@ nest::SPBuilder::connect_( const std::vector< size_t >& sources, const std::vect single_connect_( *snode_id_it, *target, tid, rng ); } } - catch ( ... ) + catch ( std::exception& err ) { - // Capture the current exception object and create an std::exception_ptr - exceptions_raised_.at( tid ) = std::current_exception(); + // We must create a new exception here, err's lifetime ends at + // the end of the catch block. + exceptions_raised_.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( err ) ); } } } diff --git a/nestkernel/connection_creator.cpp b/nestkernel/connection_creator.cpp index a8c52d661d..16bfac6da4 100644 --- a/nestkernel/connection_creator.cpp +++ b/nestkernel/connection_creator.cpp @@ -21,14 +21,12 @@ */ #include "connection_creator.h" - -#include "nest.h" -#include "spatial.h" +#include "dictutils.h" namespace nest { -ConnectionCreator::ConnectionCreator( const Dictionary& dict ) +ConnectionCreator::ConnectionCreator( DictionaryDatum dict ) : allow_autapses_( true ) , allow_multapses_( true ) , allow_oversized_( false ) @@ -39,61 +37,58 @@ ConnectionCreator::ConnectionCreator( const Dictionary& dict ) , weight_() , delay_() { - std::string connection_type; + Name connection_type; - dict.update_value( names::connection_type, connection_type ); - dict.update_value( names::allow_autapses, allow_autapses_ ); - dict.update_value( names::allow_multapses, allow_multapses_ ); - dict.update_value( names::allow_oversized_mask, allow_oversized_ ); + updateValue< std::string >( dict, names::connection_type, connection_type ); + updateValue< bool >( dict, names::allow_autapses, allow_autapses_ ); + updateValue< bool >( dict, names::allow_multapses, allow_multapses_ ); + updateValue< bool >( dict, names::allow_oversized_mask, allow_oversized_ ); // Need to store number of connections in a temporary variable to be able to detect negative values. - if ( dict.known( names::number_of_connections ) ) + + if ( dict->known( names::number_of_connections ) ) { - if ( is_type< ParameterPTR >( dict.at( names::number_of_connections ) ) ) + ParameterDatum* pd = dynamic_cast< ParameterDatum* >( ( *dict )[ names::number_of_connections ].datum() ); + if ( pd ) { - dict.update_value< ParameterPTR >( names::number_of_connections, number_of_connections_ ); + number_of_connections_ = *pd; } else { // Assume indegree is a scalar. - const long value = dict.get< long >( names::number_of_connections ); + const long value = ( *dict )[ names::number_of_connections ]; if ( value < 0 ) { throw BadProperty( "Number of connections cannot be less than zero." ); } - number_of_connections_ = ParameterPTR( new ConstantParameter( value ) ); + number_of_connections_ = std::shared_ptr< Parameter >( new ConstantParameter( value ) ); } } - if ( dict.known( names::mask ) ) + + if ( dict->known( names::mask ) ) { - mask_ = create_mask( dict.get< Dictionary >( names::mask ) ); + mask_ = NestModule::create_mask( ( *dict )[ names::mask ] ); } - if ( dict.known( names::kernel ) ) + if ( dict->known( names::kernel ) ) { - kernel_ = create_parameter( dict.at( names::kernel ) ); + kernel_ = NestModule::create_parameter( ( *dict )[ names::kernel ] ); } - - if ( dict.known( names::synapse_parameters ) ) + if ( dict->known( names::synapse_parameters ) ) { // If synapse_parameters exists, we have collocated synapses. - std::vector< Dictionary > syn_params_dvd; - - try - { - dict.update_value( names::synapse_parameters, syn_params_dvd ); - } - catch ( const nest::TypeMismatch& ) + ArrayDatum* syn_params_dvd = dynamic_cast< ArrayDatum* >( ( *dict )[ names::synapse_parameters ].datum() ); + if ( not syn_params_dvd ) { - // Give a more helpful message if the provided type is wrong. throw BadProperty( "synapse_parameters must be list of dictionaries" ); } - param_dicts_.resize( syn_params_dvd.size() ); + param_dicts_.resize( syn_params_dvd->size() ); auto param_dict = param_dicts_.begin(); - for ( auto syn_param_it = syn_params_dvd.begin(); syn_param_it < syn_params_dvd.end(); - ++syn_param_it, ++param_dict ) + for ( auto synapse_datum = syn_params_dvd->begin(); synapse_datum < syn_params_dvd->end(); + ++synapse_datum, ++param_dict ) { - extract_params_( *syn_param_it, *param_dict ); + auto syn_param = dynamic_cast< DictionaryDatum* >( synapse_datum->datum() ); + extract_params_( *syn_param, *param_dict ); } } else @@ -104,31 +99,34 @@ ConnectionCreator::ConnectionCreator( const Dictionary& dict ) extract_params_( dict, param_dicts_[ 0 ] ); } + ALL_ENTRIES_ACCESSED( *dict, "ConnectionCreator", "Unread dictionary entries: " ); + // Set default synapse_model, weight and delay if not given explicitly if ( synapse_model_.empty() ) { synapse_model_ = { kernel().model_manager.get_synapse_model_id( "static_synapse" ) }; } - Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_[ 0 ] ); + DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_[ 0 ] ); if ( weight_.empty() ) { - weight_ = { create_parameter( syn_defaults[ names::weight ] ) }; + weight_ = { NestModule::create_parameter( ( *syn_defaults )[ names::weight ] ) }; } if ( delay_.empty() ) { - if ( not syn_defaults.get< bool >( names::has_delay ) ) + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) { - delay_ = { create_parameter( numerics::nan ) }; + delay_ = { NestModule::create_parameter( numerics::nan ) }; } else { - delay_ = { create_parameter( syn_defaults[ names::delay ] ) }; + delay_ = { NestModule::create_parameter( ( *syn_defaults )[ names::delay ] ) }; } } if ( connection_type == names::pairwise_bernoulli_on_source ) { - if ( dict.known( names::number_of_connections ) ) + + if ( dict->known( names::number_of_connections ) ) { type_ = Fixed_indegree; } @@ -143,7 +141,8 @@ ConnectionCreator::ConnectionCreator( const Dictionary& dict ) } else if ( connection_type == names::pairwise_bernoulli_on_target ) { - if ( dict.known( names::number_of_connections ) ) + + if ( dict->known( names::number_of_connections ) ) { type_ = Fixed_outdegree; } @@ -159,49 +158,52 @@ ConnectionCreator::ConnectionCreator( const Dictionary& dict ) } void -ConnectionCreator::extract_params_( const Dictionary& dict, std::vector< Dictionary >& params ) +ConnectionCreator::extract_params_( const DictionaryDatum& dict_datum, std::vector< DictionaryDatum >& params ) { - const std::string syn_name = dict.known( names::synapse_model ) ? dict.get< std::string >( names::synapse_model ) - : std::string( "static_synapse" ); + if ( not dict_datum->known( names::synapse_model ) ) + { + dict_datum->insert( names::synapse_model, "static_synapse" ); + } + std::string syn_name = ( *dict_datum )[ names::synapse_model ]; // The following call will throw "UnknownSynapseType" if syn_name is not naming a known model const size_t synapse_model_id = kernel().model_manager.get_synapse_model_id( syn_name ); synapse_model_.push_back( synapse_model_id ); - Dictionary syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id ); - if ( dict.known( names::weight ) ) + DictionaryDatum syn_defaults = kernel().model_manager.get_connector_defaults( synapse_model_id ); + if ( dict_datum->known( names::weight ) ) { - weight_.push_back( create_parameter( dict.at( names::weight ) ) ); + weight_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::weight ] ) ); } else { - weight_.push_back( create_parameter( syn_defaults[ names::weight ] ) ); + weight_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::weight ] ) ); } - if ( dict.known( names::delay ) ) + if ( dict_datum->known( names::delay ) ) { - delay_.push_back( create_parameter( dict.at( names::delay ) ) ); + delay_.push_back( NestModule::create_parameter( ( *dict_datum )[ names::delay ] ) ); } else { - if ( not syn_defaults.get< bool >( names::has_delay ) ) + if ( not getValue< bool >( ( *syn_defaults )[ names::has_delay ] ) ) { - delay_.push_back( create_parameter( numerics::nan ) ); + delay_.push_back( NestModule::create_parameter( numerics::nan ) ); } else { - delay_.push_back( create_parameter( syn_defaults[ names::delay ] ) ); + delay_.push_back( NestModule::create_parameter( ( *syn_defaults )[ names::delay ] ) ); } } - Dictionary syn_dict; + DictionaryDatum syn_dict = new Dictionary(); // Using a lambda function here instead of updateValue because updateValue causes // problems when setting a value to a dictionary-entry in syn_dict. - auto copy_long_if_known = [ &syn_dict, &dict ]( const std::string& name ) -> void + auto copy_long_if_known = [ &syn_dict, &dict_datum ]( const Name& name ) -> void { - if ( dict.known( name ) ) + if ( dict_datum->known( name ) ) { - syn_dict[ name ] = dict.get< long >( name ); + ( *syn_dict )[ name ] = getValue< long >( dict_datum, name ); } }; copy_long_if_known( names::synapse_label ); diff --git a/nestkernel/kernel_manager.cpp b/nestkernel/kernel_manager.cpp index 775d6757a9..e31cea89b4 100644 --- a/nestkernel/kernel_manager.cpp +++ b/nestkernel/kernel_manager.cpp @@ -25,121 +25,6 @@ nest::KernelManager* nest::KernelManager::kernel_manager_instance_ = nullptr; - -Dictionary -nest::KernelManager::get_build_info_() -{ - // Exit codes - constexpr unsigned int EXITCODE_UNKNOWN_ERROR = 10; - constexpr unsigned int EXITCODE_USERABORT = 15; - constexpr unsigned int EXITCODE_EXCEPTION = 125; - constexpr unsigned int EXITCODE_SCRIPTERROR = 126; - constexpr unsigned int EXITCODE_FATAL = 127; - - // The range 200-215 is reserved for test skipping exitcodes. Any new codes must - // also be added to testsuite/do_tests_sh.in. - constexpr unsigned int EXITCODE_SKIPPED = 200; - constexpr unsigned int EXITCODE_SKIPPED_NO_MPI = 201; - constexpr unsigned int EXITCODE_SKIPPED_HAVE_MPI = 202; - constexpr unsigned int EXITCODE_SKIPPED_NO_THREADING = 203; - constexpr unsigned int EXITCODE_SKIPPED_NO_GSL = 204; - constexpr unsigned int EXITCODE_SKIPPED_NO_MUSIC = 205; - - Dictionary build_info; - - build_info[ "version" ] = std::string( NEST_VERSION ); - build_info[ "exitcode" ] = EXIT_SUCCESS; - build_info[ "built" ] = std::string( String::compose( "%1 %2", __DATE__, __TIME__ ) ); - build_info[ "datadir" ] = std::string( NEST_INSTALL_PREFIX "/" NEST_INSTALL_DATADIR ); - build_info[ "docdir" ] = std::string( NEST_INSTALL_PREFIX "/" NEST_INSTALL_DOCDIR ); - build_info[ "prefix" ] = std::string( NEST_INSTALL_PREFIX ); - build_info[ "host" ] = std::string( NEST_HOST ); - build_info[ "hostos" ] = std::string( NEST_HOSTOS ); - build_info[ "hostvendor" ] = std::string( NEST_HOSTVENDOR ); - build_info[ "hostcpu" ] = std::string( NEST_HOSTCPU ); - -#ifdef _OPENMP - build_info[ "have_threads" ] = true; - build_info[ "threads_model" ] = std::string( "openmp" ); -#else - build_info[ "have_threads" ] = false; -#endif - -#ifdef HAVE_MPI - build_info[ "have_mpi" ] = true; - build_info[ "mpiexec" ] = std::string( MPIEXEC ); - build_info[ "mpiexec_numproc_flag" ] = std::string( MPIEXEC_NUMPROC_FLAG ); - build_info[ "mpiexec_max_numprocs" ] = std::string( MPIEXEC_MAX_NUMPROCS ); - build_info[ "mpiexec_preflags" ] = std::string( MPIEXEC_PREFLAGS ); - build_info[ "mpiexec_postflags" ] = std::string( MPIEXEC_POSTFLAGS ); -#else - build_info[ "have_mpi" ] = false; -#endif - -#ifdef HAVE_GSL - build_info[ "have_gsl" ] = true; -#else - build_info[ "have_gsl" ] = false; -#endif - -#ifdef HAVE_BOOST - build_info[ "have_boost" ] = true; -#else - build_info[ "have_boost" ] = false; -#endif - -#ifdef HAVE_MUSIC - build_info[ "have_music" ] = true; -#else - build_info[ "have_music" ] = false; -#endif - -#ifdef HAVE_LIBNEUROSIM - build_info[ "have_libneurosim" ] = true; -#else - build_info[ "have_libneurosim" ] = false; -#endif - -#ifdef HAVE_SIONLIB - build_info[ "have_sionlib" ] = true; -#else - build_info[ "have_sionlib" ] = false; -#endif - -#ifdef HAVE_HDF5 - build_info[ "have_hdf5" ] = true; -#else - build_info[ "have_hdf5" ] = false; -#endif - -#ifdef NDEBUG - build_info[ "ndebug" ] = true; -#else - build_info[ "ndebug" ] = false; -#endif - - Dictionary exitcodes; - - exitcodes[ "success" ] = EXIT_SUCCESS; - exitcodes[ "skipped" ] = EXITCODE_SKIPPED; - exitcodes[ "skipped_no_mpi" ] = EXITCODE_SKIPPED_NO_MPI; - exitcodes[ "skipped_have_mpi" ] = EXITCODE_SKIPPED_HAVE_MPI; - exitcodes[ "skipped_no_threading" ] = EXITCODE_SKIPPED_NO_THREADING; - exitcodes[ "skipped_no_gsl" ] = EXITCODE_SKIPPED_NO_GSL; - exitcodes[ "skipped_no_music" ] = EXITCODE_SKIPPED_NO_MUSIC; - exitcodes[ "scripterror" ] = EXITCODE_SCRIPTERROR; - exitcodes[ "abort" ] = NEST_EXITCODE_ABORT; - exitcodes[ "userabort" ] = EXITCODE_USERABORT; - exitcodes[ "segfault" ] = NEST_EXITCODE_SEGFAULT; - exitcodes[ "exception" ] = EXITCODE_EXCEPTION; - exitcodes[ "fatal" ] = EXITCODE_FATAL; - exitcodes[ "unknownerror" ] = EXITCODE_UNKNOWN_ERROR; - - build_info[ "test_exitcodes" ] = exitcodes; - - return build_info; -} - void nest::KernelManager::create_kernel_manager() { @@ -154,6 +39,13 @@ nest::KernelManager::create_kernel_manager() #pragma omp barrier } +void +nest::KernelManager::destroy_kernel_manager() +{ + kernel_manager_instance_->logging_manager.set_logging_level( M_QUIET ); + delete kernel_manager_instance_; +} + nest::KernelManager::KernelManager() : fingerprint_( 0 ) , logging_manager() @@ -291,7 +183,7 @@ nest::KernelManager::change_number_of_threads( size_t new_num_threads ) } void -nest::KernelManager::set_status( const Dictionary& dict ) +nest::KernelManager::set_status( const DictionaryDatum& dict ) { assert( is_initialized() ); @@ -302,7 +194,7 @@ nest::KernelManager::set_status( const Dictionary& dict ) } void -nest::KernelManager::get_status( Dictionary& dict ) +nest::KernelManager::get_status( DictionaryDatum& dict ) { assert( is_initialized() ); @@ -311,21 +203,6 @@ nest::KernelManager::get_status( Dictionary& dict ) manager->get_status( dict ); } - dict[ "build_info" ] = get_build_info_(); - if ( NEST_HOSTOS == std::string( "linux" ) ) - { - dict[ "memory_size" ] = get_memsize_linux_(); - } - else if ( NEST_HOSTOS == std::string( "darwin" ) ) - { - dict[ "memory_size" ] = get_memsize_darwin_(); - } - else - { - // Not available for this OS. - dict[ "memory_size" ] = -1; - } - sw_omp_synchronization_construction_.get_status( dict, names::time_omp_synchronization_construction, names::time_omp_synchronization_construction_cpu ); sw_omp_synchronization_simulation_.get_status( @@ -342,80 +219,3 @@ nest::KernelManager::write_to_dump( const std::string& msg ) dump_ << msg << std::endl << std::flush; } } - -#ifdef __linux__ - -#include -#include -size_t -nest::KernelManager::get_memsize_linux_() const -{ - // code based on mistral.ai - std::ifstream file( "/proc/self/status" ); - if ( not file.is_open() ) - { - throw std::runtime_error( "Could not open /proc/self/status" ); - } - - std::string line; - while ( std::getline( file, line ) ) - { - if ( line.rfind( "VmSize:", 0 ) == 0 ) - { - std::istringstream stream( line ); - std::string key; - size_t value; - std::string unit; - stream >> key >> value >> unit; - file.close(); - if ( unit != "kB" ) - { - throw std::runtime_error( "VmSize not reported in kB" ); - } - return value; - } - } - - file.close(); - throw std::runtime_error( "VmSize not found in /proc/self/status" ); -} - -#else - -size_t -nest::KernelManager::get_memsize_linux_() const -{ - assert( false || "Only implemented on Linux systems." ); - return 0; -} - -#endif - - -#if defined __APPLE__ - -#include -size_t -nest::KernelManager::get_memsize_darwin_() const -{ - struct task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - - kern_return_t result = task_info( mach_task_self(), TASK_BASIC_INFO, ( task_info_t ) &t_info, &t_info_count ); - assert( result == KERN_SUCCESS || "Problem occurred during getting of task_info." ); - - // For macOS, vmsize is not informative, it is an extremly large address range, usually O(2^40). - // resident_size gives the most reasonable information. Information is in bytes, thus divide. - return t_info.resident_size / 1024; -} - -#else - -size_t -nest::KernelManager::get_memsize_darwin_() const -{ - assert( false || "Only implemented on macOS." ); - return 0; -} - -#endif diff --git a/nestkernel/spatial.cpp b/nestkernel/spatial.cpp index 87e4c7e6bd..8063eab1c3 100644 --- a/nestkernel/spatial.cpp +++ b/nestkernel/spatial.cpp @@ -23,8 +23,6 @@ #include "spatial.h" // C++ includes: -#include -#include #include #include @@ -35,8 +33,12 @@ #include "exceptions.h" #include "kernel_manager.h" #include "nest.h" +#include "nestmodule.h" #include "node.h" +// Includes from sli: +#include "sliexceptions.h" + // Includes from spatial: #include "grid_layer.h" #include "layer_impl.h" @@ -66,25 +68,25 @@ get_layer( NodeCollectionPTR nc ) } NodeCollectionPTR -create_layer( const Dictionary& layer_dict ) +create_layer( const DictionaryDatum& layer_dict ) { - layer_dict.init_access_flags(); + layer_dict->clear_access_flags(); NodeCollectionPTR layer = AbstractLayer::create_layer( layer_dict ); - layer_dict.all_entries_accessed( "CreateLayer", "params" ); + ALL_ENTRIES_ACCESSED( *layer_dict, "nest::CreateLayer", "Unread dictionary entries: " ); return layer; } -std::vector< std::vector< double > > +ArrayDatum get_position( NodeCollectionPTR layer_nc ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); - std::vector< std::vector< double > > result; + ArrayDatum result; result.reserve( layer_nc->size() ); for ( NodeCollection::const_iterator it = layer_nc->begin(); it < layer_nc->end(); ++it ) @@ -97,7 +99,7 @@ get_position( NodeCollectionPTR layer_nc ) } const long lid = node_id - first_node_id; - const auto arr = layer->get_position_vector( lid ); + Token arr = layer->get_position_vector( lid ); result.push_back( arr ); } @@ -131,17 +133,17 @@ get_position( const size_t node_id ) return pos_vec; } -std::vector< std::vector< double > > +ArrayDatum displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) { - auto layer_to_positions = get_position( layer_to_nc ); + ArrayDatum layer_to_positions = get_position( layer_to_nc ); AbstractLayerPTR layer_from = get_layer( layer_from_nc ); NodeCollectionMetadataPTR meta = layer_from_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); int counter = 0; - std::vector< std::vector< double > > result; + ArrayDatum result; // If layer_from has size equal to one, but layer_to do not, we want the displacement between every node // in layer_to against the one in layer_from. Likewise if layer_to has size 1 and layer_from do not. @@ -155,9 +157,11 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; // If layer_from has size 1, we need to iterate over the layer_to positions - for ( auto& pos : layer_to_positions ) + for ( Token const* it = layer_to_positions.begin(); it != layer_to_positions.end(); ++it ) { - result.push_back( layer_from->compute_displacement( pos, lid ) ); + std::vector< double > pos = getValue< std::vector< double > >( *it ); + Token disp = layer_from->compute_displacement( pos, lid ); + result.push_back( disp ); } } else @@ -171,8 +175,10 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) } const long lid = node_id - first_node_id; - const auto pos = layer_to_positions[ counter ]; - result.push_back( layer_from->compute_displacement( pos, lid ) ); + + std::vector< double > pos = getValue< std::vector< double > >( layer_to_positions[ counter ] ); + Token disp = layer_from->compute_displacement( pos, lid ); + result.push_back( disp ); // We only iterate the layer_to positions vector if it has more than one // element. @@ -186,15 +192,15 @@ displacement( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) return result; } -std::vector< std::vector< double > > -displacement( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > >& point ) +ArrayDatum +displacement( NodeCollectionPTR layer_nc, const ArrayDatum point ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); size_t first_node_id = meta->get_first_node_id(); int counter = 0; - std::vector< std::vector< double > > result; + ArrayDatum result; for ( NodeCollection::const_iterator it = layer_nc->begin(); it != layer_nc->end(); ++it ) { size_t node_id = ( *it ).node_id; @@ -205,8 +211,9 @@ displacement( NodeCollectionPTR layer_nc, const std::vector< std::vector< double const long lid = node_id - first_node_id; - const auto pos = point[ counter ]; - result.push_back( layer->compute_displacement( pos, lid ) ); + std::vector< double > pos = getValue< std::vector< double > >( point[ counter ] ); + Token disp = layer->compute_displacement( pos, lid ); + result.push_back( disp ); // We only iterate the positions vector if it has more than one // element. @@ -221,12 +228,7 @@ displacement( NodeCollectionPTR layer_nc, const std::vector< std::vector< double std::vector< double > distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) { - if ( layer_to_nc->size() != 1 and layer_from_nc->size() != 1 and not( layer_to_nc->size() == layer_from_nc->size() ) ) - { - throw BadProperty( "NodeCollections must have equal length or one must have size 1." ); - } - - auto layer_to_positions = get_position( layer_to_nc ); + ArrayDatum layer_to_positions = get_position( layer_to_nc ); AbstractLayerPTR layer_from = get_layer( layer_from_nc ); NodeCollectionMetadataPTR meta = layer_from_nc->get_metadata(); @@ -247,9 +249,11 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; // If layer_from has size 1, we need to iterate over the layer_to positions - for ( auto& pos : layer_to_positions ) + for ( Token const* it = layer_to_positions.begin(); it != layer_to_positions.end(); ++it ) { - result.push_back( layer_from->compute_distance( pos, lid ) ); + std::vector< double > pos = getValue< std::vector< double > >( *it ); + double disp = layer_from->compute_distance( pos, lid ); + result.push_back( disp ); } } else @@ -264,8 +268,8 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) const long lid = node_id - first_node_id; - const auto pos = layer_to_positions[ counter ]; - const double disp = layer_from->compute_distance( pos, lid ); + std::vector< double > pos = getValue< std::vector< double > >( layer_to_positions[ counter ] ); + double disp = layer_from->compute_distance( pos, lid ); result.push_back( disp ); // We only iterate the layer_to positions vector if it has more than one @@ -281,7 +285,7 @@ distance( NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc ) } std::vector< double > -distance( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > >& point ) +distance( NodeCollectionPTR layer_nc, const ArrayDatum point ) { AbstractLayerPTR layer = get_layer( layer_nc ); NodeCollectionMetadataPTR meta = layer_nc->get_metadata(); @@ -299,7 +303,7 @@ distance( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > > const long lid = node_id - first_node_id; - const auto pos = point[ counter ]; + std::vector< double > pos = getValue< std::vector< double > >( point[ counter ] ); double disp = layer->compute_distance( pos, lid ); result.push_back( disp ); @@ -314,15 +318,17 @@ distance( NodeCollectionPTR layer_nc, const std::vector< std::vector< double > > } std::vector< double > -distance( const std::vector< ConnectionID >& conns ) +distance( const ArrayDatum conns ) { std::vector< double > result; size_t num_conns = conns.size(); result.reserve( num_conns ); - for ( auto& conn_id : conns ) + for ( size_t conn_indx = 0; conn_indx < num_conns; ++conn_indx ) { + ConnectionDatum conn_id = getValue< ConnectionDatum >( conns.get( conn_indx ) ); + size_t src = conn_id.get_source_node_id(); auto src_position = get_position( src ); @@ -354,222 +360,92 @@ distance( const std::vector< ConnectionID >& conns ) return result; } -MaskPTR -create_mask( const Dictionary& mask_dict ) -{ - mask_dict.init_access_flags(); - - // The dictionary should contain one key which is the name of the - // mask type, and optionally the key 'anchor'. To find the unknown - // mask type key, we must loop through all keys. - bool has_anchor = false; - MaskPTR mask; - - for ( auto& kv : mask_dict ) - { - if ( kv.first == names::anchor ) - { - has_anchor = true; - } - else - { - mask = create_mask( kv.first, mask_dict.get< Dictionary >( kv.first ) ); - } - } - - if ( has_anchor ) - { - // The anchor may be an array of doubles (a spatial position). - // For grid layers only, it is also possible to provide an array of longs. - try - { - const std::vector< long >& anchor = mask_dict.get< std::vector< long > >( names::anchor ); - - switch ( anchor.size() ) - { - case 2: - try - { - auto& grid_mask_2d = dynamic_cast< GridMask< 2 >& >( *mask ); - grid_mask_2d.set_anchor( Position< 2, int >( anchor[ 0 ], anchor[ 1 ] ) ); - } - catch ( std::bad_cast& e ) - { - throw BadProperty( "Mask must be 2-dimensional grid mask." ); - } - break; - case 3: - try - { - auto& grid_mask_3d = dynamic_cast< GridMask< 3 >& >( *mask ); - grid_mask_3d.set_anchor( Position< 3, int >( anchor[ 0 ], anchor[ 1 ], anchor[ 2 ] ) ); - } - catch ( std::bad_cast& e ) - { - throw BadProperty( "Mask must be 3-dimensional grid mask." ); - } - break; - default: - throw BadProperty( "Anchor must be 2- or 3-dimensional." ); - } - } - catch ( TypeMismatch& e ) - { - std::vector< double > double_anchor = mask_dict.get< std::vector< double > >( names::anchor ); - std::shared_ptr< AbstractMask > amask; - - switch ( double_anchor.size() ) - { - case 2: - amask = std::shared_ptr< AbstractMask >( - new AnchoredMask< 2 >( dynamic_cast< Mask< 2 >& >( *mask ), double_anchor ) ); - break; - case 3: - amask = std::shared_ptr< AbstractMask >( - new AnchoredMask< 3 >( dynamic_cast< Mask< 3 >& >( *mask ), double_anchor ) ); - break; - default: - throw BadProperty( "Anchor must be 2- or 3-dimensional." ); - } - - mask = amask; - } - } - mask_dict.all_entries_accessed( "CreateMask", "mask_dict" ); - - return mask; -} - -NodeCollectionPTR -select_nodes_by_mask( const NodeCollectionPTR layer_nc, const std::vector< double >& anchor, const MaskPTR mask ) +MaskDatum +create_mask( const DictionaryDatum& mask_dict ) { - std::vector< size_t > mask_node_ids; + mask_dict->clear_access_flags(); - const auto dim = anchor.size(); + MaskDatum datum( NestModule::create_mask( mask_dict ) ); - if ( dim != 2 and dim != 3 ) - { - throw BadProperty( "Center must be 2- or 3-dimensional." ); - } - - AbstractLayerPTR abstract_layer = get_layer( layer_nc ); - - if ( dim == 2 ) - { - auto layer = dynamic_cast< Layer< 2 >* >( abstract_layer.get() ); - if ( not layer ) - { - throw TypeMismatch( "2D layer", "other type" ); - } + ALL_ENTRIES_ACCESSED( *mask_dict, "nest::CreateMask", "Unread dictionary entries: " ); - auto ml = MaskedLayer< 2 >( *layer, mask, false, layer_nc ); - - for ( Ntree< 2, size_t >::masked_iterator it = ml.begin( Position< 2 >( anchor[ 0 ], anchor[ 1 ] ) ); - it != ml.end(); - ++it ) - { - mask_node_ids.push_back( it->second ); - } - } - else - { - auto layer = dynamic_cast< Layer< 3 >* >( abstract_layer.get() ); - if ( not layer ) - { - throw TypeMismatch( "3D layer", "other type" ); - } - - auto ml = MaskedLayer< 3 >( *layer, mask, false, layer_nc ); - - for ( Ntree< 3, size_t >::masked_iterator it = ml.begin( Position< 3 >( anchor[ 0 ], anchor[ 1 ], anchor[ 2 ] ) ); - it != ml.end(); - ++it ) - { - mask_node_ids.push_back( it->second ); - } - } - // Nodes must be sorted when creating a NodeCollection - std::sort( mask_node_ids.begin(), mask_node_ids.end() ); - return NodeCollection::create( mask_node_ids ); + return datum; } -bool -inside( const std::vector< double >& point, const MaskPTR mask ) +BoolDatum +inside( const std::vector< double >& point, const MaskDatum& mask ) { return mask->inside( point ); } -MaskPTR -intersect_mask( const MaskPTR mask1, const MaskPTR mask2 ) +MaskDatum +intersect_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) { - return MaskPTR( mask1->intersect_mask( *mask2 ) ); + return mask1->intersect_mask( *mask2 ); } -MaskPTR -union_mask( const MaskPTR mask1, const MaskPTR mask2 ) +MaskDatum +union_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) { - return MaskPTR( mask1->union_mask( *mask2 ) ); + return mask1->union_mask( *mask2 ); } -MaskPTR -minus_mask( const MaskPTR mask1, const MaskPTR mask2 ) +MaskDatum +minus_mask( const MaskDatum& mask1, const MaskDatum& mask2 ) { - return MaskPTR( mask1->minus_mask( *mask2 ) ); + return mask1->minus_mask( *mask2 ); } void -connect_layers( NodeCollectionPTR source_nc, NodeCollectionPTR target_nc, const Dictionary& connection_dict ) +connect_layers( NodeCollectionPTR source_nc, NodeCollectionPTR target_nc, const DictionaryDatum& connection_dict ) { AbstractLayerPTR source = get_layer( source_nc ); AbstractLayerPTR target = get_layer( target_nc ); - connection_dict.init_access_flags(); + connection_dict->clear_access_flags(); ConnectionCreator connector( connection_dict ); - connection_dict.all_entries_accessed( "ConnectLayers", "connection_dict" ); + ALL_ENTRIES_ACCESSED( *connection_dict, "nest::CreateLayers", "Unread dictionary entries: " ); kernel().node_manager.update_thread_local_node_data(); // Set flag before calling source->connect() in case exception is thrown after some connections have been created. kernel().connection_manager.set_connections_have_changed(); + source->connect( source_nc, target, target_nc, connector ); } void -dump_layer_nodes( const NodeCollectionPTR layer_nc, const std::string& filename ) +dump_layer_nodes( NodeCollectionPTR layer_nc, OstreamDatum& out ) { AbstractLayerPTR layer = get_layer( layer_nc ); - std::ofstream out( filename ); - if ( out.good() ) + if ( out->good() ) { - layer->dump_nodes( out ); + layer->dump_nodes( *out ); } - out.close(); } void -dump_layer_connections( const NodeCollectionPTR source_layer_nc, - const NodeCollectionPTR target_layer_nc, - const std::string& syn_model, - const std::string& filename ) +dump_layer_connections( const Token& syn_model, + NodeCollectionPTR source_layer_nc, + NodeCollectionPTR target_layer_nc, + OstreamDatum& out ) { AbstractLayerPTR source_layer = get_layer( source_layer_nc ); AbstractLayerPTR target_layer = get_layer( target_layer_nc ); - std::ofstream out( filename ); - if ( out.good() ) + if ( out->good() ) { - source_layer->dump_connections( out, source_layer_nc, target_layer, syn_model ); + source_layer->dump_connections( *out, source_layer_nc, target_layer, syn_model ); } - out.close(); } -Dictionary +DictionaryDatum get_layer_status( NodeCollectionPTR ) { assert( false and "not implemented" ); - return {}; + return DictionaryDatum(); } } // namespace nest diff --git a/nestkernel/structural_plasticity_node.cpp b/nestkernel/structural_plasticity_node.cpp index 2b04c939d5..e590849d83 100644 --- a/nestkernel/structural_plasticity_node.cpp +++ b/nestkernel/structural_plasticity_node.cpp @@ -25,6 +25,8 @@ // Includes from nestkernel: #include "kernel_manager.h" +// Includes from sli: +#include "dictutils.h" namespace nest { @@ -49,35 +51,37 @@ nest::StructuralPlasticityNode::StructuralPlasticityNode( const StructuralPlasti } void -nest::StructuralPlasticityNode::get_status( Dictionary& d ) const +nest::StructuralPlasticityNode::get_status( DictionaryDatum& d ) const { + DictionaryDatum synaptic_elements_d; + DictionaryDatum synaptic_element_d; - d[ names::Ca ] = Ca_minus_; - d[ names::tau_Ca ] = tau_Ca_; - d[ names::beta_Ca ] = beta_Ca_; + def< double >( d, names::Ca, Ca_minus_ ); + def< double >( d, names::tau_Ca, tau_Ca_ ); + def< double >( d, names::beta_Ca, beta_Ca_ ); - Dictionary synaptic_elements_d; - for ( std::map< std::string, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); + synaptic_elements_d = DictionaryDatum( new Dictionary ); + def< DictionaryDatum >( d, names::synaptic_elements, synaptic_elements_d ); + for ( std::map< Name, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); ++it ) { - Dictionary synaptic_element_d; + synaptic_element_d = DictionaryDatum( new Dictionary ); + def< DictionaryDatum >( synaptic_elements_d, it->first, synaptic_element_d ); it->second.get( synaptic_element_d ); - synaptic_elements_d[ it->first ] = synaptic_element_d; } - d[ names::synaptic_elements ] = synaptic_elements_d; } void -nest::StructuralPlasticityNode::set_status( const Dictionary& d ) +nest::StructuralPlasticityNode::set_status( const DictionaryDatum& d ) { // We need to preserve values in case invalid values are set double new_Ca_ = Ca_minus_; double new_tau_Ca = tau_Ca_; double new_beta_Ca = beta_Ca_; - d.update_value( names::Ca, new_Ca_ ); - d.update_value( names::tau_Ca, new_tau_Ca ); - d.update_value( names::beta_Ca, new_beta_Ca ); + updateValue< double >( d, names::Ca, new_Ca_ ); + updateValue< double >( d, names::tau_Ca, new_tau_Ca ); + updateValue< double >( d, names::beta_Ca, new_beta_Ca ); if ( new_Ca_ < 0.0 ) { @@ -101,43 +105,42 @@ nest::StructuralPlasticityNode::set_status( const Dictionary& d ) // check, if to clear spike history and K_minus bool clear = false; - d.update_value( names::clear, clear ); + updateValue< bool >( d, names::clear, clear ); if ( clear ) { clear_history(); } - if ( d.known( names::synaptic_elements_param ) ) + if ( d->known( names::synaptic_elements_param ) ) { - const Dictionary synaptic_elements_dict = d.get< Dictionary >( names::synaptic_elements_param ); + const DictionaryDatum synaptic_elements_dict = getValue< DictionaryDatum >( d, names::synaptic_elements_param ); - for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); ++it ) { - if ( synaptic_elements_dict.known( it->first ) ) + if ( synaptic_elements_dict->known( it->first ) ) { - const Dictionary synaptic_elements_a = synaptic_elements_dict.get< Dictionary >( it->first ); + const DictionaryDatum synaptic_elements_a = getValue< DictionaryDatum >( synaptic_elements_dict, it->first ); it->second.set( synaptic_elements_a ); } } } - if ( not d.known( names::synaptic_elements ) ) + if ( not d->known( names::synaptic_elements ) ) { return; } // we replace the existing synaptic_elements_map_ by the new one - Dictionary synaptic_elements_d; - std::pair< std::map< std::string, SynapticElement >::iterator, bool > insert_result; + DictionaryDatum synaptic_elements_d; + std::pair< std::map< Name, SynapticElement >::iterator, bool > insert_result; - synaptic_elements_map_ = std::map< std::string, SynapticElement >(); - synaptic_elements_d = d.get< Dictionary >( names::synaptic_elements ); + synaptic_elements_map_ = std::map< Name, SynapticElement >(); + synaptic_elements_d = getValue< DictionaryDatum >( d, names::synaptic_elements ); - for ( auto& syn_element : synaptic_elements_d ) + for ( Dictionary::const_iterator i = synaptic_elements_d->begin(); i != synaptic_elements_d->end(); ++i ) { - SynapticElement se; - se.set( synaptic_elements_d.get< Dictionary >( syn_element.first ) ); - synaptic_elements_map_.insert( std::pair< std::string, SynapticElement >( syn_element.first, se ) ); + insert_result = synaptic_elements_map_.insert( std::pair< Name, SynapticElement >( i->first, SynapticElement() ) ); + ( insert_result.first->second ).set( getValue< DictionaryDatum >( synaptic_elements_d, i->first ) ); } } @@ -149,9 +152,9 @@ nest::StructuralPlasticityNode::clear_history() } double -nest::StructuralPlasticityNode::get_synaptic_elements( std::string n ) const +nest::StructuralPlasticityNode::get_synaptic_elements( Name n ) const { - std::map< std::string, SynapticElement >::const_iterator se_it; + std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); double z_value; @@ -174,9 +177,9 @@ nest::StructuralPlasticityNode::get_synaptic_elements( std::string n ) const } int -nest::StructuralPlasticityNode::get_synaptic_elements_vacant( std::string n ) const +nest::StructuralPlasticityNode::get_synaptic_elements_vacant( Name n ) const { - std::map< std::string, SynapticElement >::const_iterator se_it; + std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); if ( se_it != synaptic_elements_map_.end() ) @@ -190,9 +193,9 @@ nest::StructuralPlasticityNode::get_synaptic_elements_vacant( std::string n ) co } int -nest::StructuralPlasticityNode::get_synaptic_elements_connected( std::string n ) const +nest::StructuralPlasticityNode::get_synaptic_elements_connected( Name n ) const { - std::map< std::string, SynapticElement >::const_iterator se_it; + std::map< Name, SynapticElement >::const_iterator se_it; se_it = synaptic_elements_map_.find( n ); if ( se_it != synaptic_elements_map_.end() ) @@ -205,16 +208,16 @@ nest::StructuralPlasticityNode::get_synaptic_elements_connected( std::string n ) } } -std::map< std::string, double > +std::map< Name, double > nest::StructuralPlasticityNode::get_synaptic_elements() const { - std::map< std::string, double > n_map; + std::map< Name, double > n_map; - for ( std::map< std::string, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); + for ( std::map< Name, SynapticElement >::const_iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); ++it ) { - n_map.insert( std::pair< std::string, double >( it->first, get_synaptic_elements( it->first ) ) ); + n_map.insert( std::pair< Name, double >( it->first, get_synaptic_elements( it->first ) ) ); } return n_map; } @@ -224,7 +227,7 @@ nest::StructuralPlasticityNode::update_synaptic_elements( double t ) { assert( t >= Ca_t_ ); - for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); ++it ) { @@ -238,7 +241,7 @@ nest::StructuralPlasticityNode::update_synaptic_elements( double t ) void nest::StructuralPlasticityNode::decay_synaptic_elements_vacant() { - for ( std::map< std::string, SynapticElement >::iterator it = synaptic_elements_map_.begin(); + for ( std::map< Name, SynapticElement >::iterator it = synaptic_elements_map_.begin(); it != synaptic_elements_map_.end(); ++it ) { @@ -247,9 +250,9 @@ nest::StructuralPlasticityNode::decay_synaptic_elements_vacant() } void -nest::StructuralPlasticityNode::connect_synaptic_element( std::string name, int n ) +nest::StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) { - std::map< std::string, SynapticElement >::iterator se_it; + std::map< Name, SynapticElement >::iterator se_it; se_it = synaptic_elements_map_.find( name ); if ( se_it != synaptic_elements_map_.end() ) From d0a497a160c47d79cd77a5fd846588cd9269dc0b Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 12:57:34 +0100 Subject: [PATCH 04/10] bump CI tool versions to same as pre-commit --- .github/workflows/nestbuildmatrix.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nestbuildmatrix.yml b/.github/workflows/nestbuildmatrix.yml index 9ffe218701..5ecce2121b 100644 --- a/.github/workflows/nestbuildmatrix.yml +++ b/.github/workflows/nestbuildmatrix.yml @@ -10,7 +10,7 @@ jobs: clang-format: runs-on: "ubuntu-22.04" env: - CLANG_REQUIRE_VERSION: 17.0.4 + CLANG_REQUIRE_VERSION: 21.1.7 CLANG_FORMAT_FILE: ".clang-format" steps: - name: Harden Runner @@ -62,7 +62,7 @@ jobs: - name: "Set up Python 3.x" uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: 3.9 + python-version: 3.10 - name: "Install dependencies" run: | From df16875caf886cb0b9117fe946af2ce143d00285 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 13:01:07 +0100 Subject: [PATCH 05/10] fix YAML pitfall: version 3.10 interpreted as float 3.1 --- .github/workflows/nestbuildmatrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nestbuildmatrix.yml b/.github/workflows/nestbuildmatrix.yml index 5ecce2121b..cc79053314 100644 --- a/.github/workflows/nestbuildmatrix.yml +++ b/.github/workflows/nestbuildmatrix.yml @@ -62,7 +62,7 @@ jobs: - name: "Set up Python 3.x" uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: 3.10 + python-version: "3.10" - name: "Install dependencies" run: | From 54093fead3676ee8e0796ee7a4fc9652492f5cb6 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 13:08:22 +0100 Subject: [PATCH 06/10] =?UTF-8?q?newly=20added=20pre-commit=E2=86=92pylint?= =?UTF-8?q?=20is=20used=20from?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/nestbuildmatrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nestbuildmatrix.yml b/.github/workflows/nestbuildmatrix.yml index cc79053314..db0453f8ee 100644 --- a/.github/workflows/nestbuildmatrix.yml +++ b/.github/workflows/nestbuildmatrix.yml @@ -66,7 +66,7 @@ jobs: - name: "Install dependencies" run: | - pip install pre-commit + pip install pre-commit pylint - name: "Run pre-commit checks..." run: | From b3f7c1f68f7b9276cf80c5d89fc67f612fde6f7b Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 13:36:47 +0100 Subject: [PATCH 07/10] make testsuite directories packages for valid imports --- testsuite/pytests/__init__.py | 0 testsuite/pytests/mpi/__init__.py | 0 testsuite/pytests/mpi/nproc2/__init__.py | 0 testsuite/pytests/mpi/nproc3/__init__.py | 0 testsuite/pytests/mpi/nproc4/__init__.py | 0 testsuite/pytests/test_sp/__init__.py | 0 testsuite/pytests/test_spatial/__init__.py | 0 .../pytests/test_spatial/spatial_test_references/__init__.py | 0 .../test_spatial/spatial_test_references/circular/__init__.py | 0 .../pytests/test_spatial/spatial_test_references/free/__init__.py | 0 .../spatial_test_references/free/circular/__init__.py | 0 .../spatial_test_references/free/doughnut/__init__.py | 0 .../spatial_test_references/free/rectangular/__init__.py | 0 .../pytests/test_spatial/spatial_test_references/grid/__init__.py | 0 .../spatial_test_references/grid/circular/__init__.py | 0 .../spatial_test_references/grid/doughnut/__init__.py | 0 .../test_spatial/spatial_test_references/grid/grid/__init__.py | 0 .../spatial_test_references/grid/rectangular/__init__.py | 0 testsuite/pytests/utilities/__init__.py | 0 19 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 testsuite/pytests/__init__.py create mode 100644 testsuite/pytests/mpi/__init__.py create mode 100644 testsuite/pytests/mpi/nproc2/__init__.py create mode 100644 testsuite/pytests/mpi/nproc3/__init__.py create mode 100644 testsuite/pytests/mpi/nproc4/__init__.py create mode 100644 testsuite/pytests/test_sp/__init__.py create mode 100644 testsuite/pytests/test_spatial/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/circular/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/free/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/free/circular/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/free/doughnut/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/free/rectangular/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/grid/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/grid/circular/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/grid/doughnut/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/grid/grid/__init__.py create mode 100644 testsuite/pytests/test_spatial/spatial_test_references/grid/rectangular/__init__.py create mode 100644 testsuite/pytests/utilities/__init__.py diff --git a/testsuite/pytests/__init__.py b/testsuite/pytests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/mpi/__init__.py b/testsuite/pytests/mpi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/mpi/nproc2/__init__.py b/testsuite/pytests/mpi/nproc2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/mpi/nproc3/__init__.py b/testsuite/pytests/mpi/nproc3/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/mpi/nproc4/__init__.py b/testsuite/pytests/mpi/nproc4/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_sp/__init__.py b/testsuite/pytests/test_sp/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/__init__.py b/testsuite/pytests/test_spatial/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/circular/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/circular/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/free/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/free/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/free/circular/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/free/circular/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/free/doughnut/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/free/doughnut/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/free/rectangular/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/free/rectangular/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/grid/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/grid/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/grid/circular/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/grid/circular/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/grid/doughnut/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/grid/doughnut/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/grid/grid/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/grid/grid/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/test_spatial/spatial_test_references/grid/rectangular/__init__.py b/testsuite/pytests/test_spatial/spatial_test_references/grid/rectangular/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/pytests/utilities/__init__.py b/testsuite/pytests/utilities/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 71728766df5b7304000686b4f9715a5c8d78f8a2 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 13:54:57 +0100 Subject: [PATCH 08/10] do not require copyright headers in empty files --- build_support/check_copyright_headers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_support/check_copyright_headers.py b/build_support/check_copyright_headers.py index b7c2147963..0e52418b49 100644 --- a/build_support/check_copyright_headers.py +++ b/build_support/check_copyright_headers.py @@ -118,6 +118,9 @@ def eprint(*args, **kwargs): if any([exclude_file in tested_file for exclude_file in exclude_files]): continue + if os.stat(tested_file).st_size == 0: + continue + with open(tested_file, encoding="utf-8") as source_file: total_files += 1 for template_line in template_contents[extension]: From e10b5fafafbb00f1e5a20f605bf8ada74b3dfcd4 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Fri, 5 Dec 2025 15:13:26 +0100 Subject: [PATCH 09/10] remove unnecessary and breaking import --- testsuite/pytests/test_connect_pairwise_poisson.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/pytests/test_connect_pairwise_poisson.py b/testsuite/pytests/test_connect_pairwise_poisson.py index 0270bcef77..77c892604b 100644 --- a/testsuite/pytests/test_connect_pairwise_poisson.py +++ b/testsuite/pytests/test_connect_pairwise_poisson.py @@ -25,7 +25,6 @@ import nest import numpy as np import scipy.stats -from connect_test_base import get_connectivity_matrix from . import connect_test_base From cd8f2d0db541be6c88494d986e6b3a8796a225b3 Mon Sep 17 00:00:00 2001 From: Dennis Terhorst Date: Tue, 9 Dec 2025 12:28:20 +0100 Subject: [PATCH 10/10] remove relative imports from base pytests --- testsuite/pytests/test_connect_all_to_all.py | 3 +-- testsuite/pytests/test_connect_fixed_indegree.py | 3 +-- testsuite/pytests/test_connect_fixed_outdegree.py | 3 +-- testsuite/pytests/test_connect_fixed_total_number.py | 3 +-- testsuite/pytests/test_connect_one_to_one.py | 3 +-- testsuite/pytests/test_connect_pairwise_bernoulli.py | 3 +-- testsuite/pytests/test_connect_pairwise_poisson.py | 3 +-- testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py | 3 +-- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/testsuite/pytests/test_connect_all_to_all.py b/testsuite/pytests/test_connect_all_to_all.py index 38b78cfdd4..cb473cdb0e 100644 --- a/testsuite/pytests/test_connect_all_to_all.py +++ b/testsuite/pytests/test_connect_all_to_all.py @@ -22,12 +22,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_MPI = nest.ll_api.sli_func("statusdict/have_mpi ::") HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_indegree.py b/testsuite/pytests/test_connect_fixed_indegree.py index 964dce6e7c..9324f27dc3 100644 --- a/testsuite/pytests/test_connect_fixed_indegree.py +++ b/testsuite/pytests/test_connect_fixed_indegree.py @@ -22,12 +22,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_outdegree.py b/testsuite/pytests/test_connect_fixed_outdegree.py index 78089bef9c..01240a58d3 100644 --- a/testsuite/pytests/test_connect_fixed_outdegree.py +++ b/testsuite/pytests/test_connect_fixed_outdegree.py @@ -21,12 +21,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_fixed_total_number.py b/testsuite/pytests/test_connect_fixed_total_number.py index 0e2cafdd82..d56ade993d 100644 --- a/testsuite/pytests/test_connect_fixed_total_number.py +++ b/testsuite/pytests/test_connect_fixed_total_number.py @@ -21,12 +21,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_one_to_one.py b/testsuite/pytests/test_connect_one_to_one.py index 5f3175f72a..7bcce2f8f4 100644 --- a/testsuite/pytests/test_connect_one_to_one.py +++ b/testsuite/pytests/test_connect_one_to_one.py @@ -21,11 +21,10 @@ import unittest +import connect_test_base import nest import numpy as np -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_pairwise_bernoulli.py b/testsuite/pytests/test_connect_pairwise_bernoulli.py index 576fcd419e..cb8e2a110e 100644 --- a/testsuite/pytests/test_connect_pairwise_bernoulli.py +++ b/testsuite/pytests/test_connect_pairwise_bernoulli.py @@ -22,12 +22,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_pairwise_poisson.py b/testsuite/pytests/test_connect_pairwise_poisson.py index 77c892604b..ab7138647e 100644 --- a/testsuite/pytests/test_connect_pairwise_poisson.py +++ b/testsuite/pytests/test_connect_pairwise_poisson.py @@ -22,12 +22,11 @@ import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded") diff --git a/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py b/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py index 335f1adb2b..f7c663fe7d 100644 --- a/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py +++ b/testsuite/pytests/test_connect_symmetric_pairwise_bernoulli.py @@ -23,12 +23,11 @@ import collections import unittest +import connect_test_base import nest import numpy as np import scipy.stats -from . import connect_test_base - HAVE_OPENMP = nest.ll_api.sli_func("is_threaded")